在这个例子中,我们将把秘密和非秘密的配置文件装入Pod。对于秘密,我们将使用两种方法。使用secret.yaml 文件和在Kubernetes集群中手动创建秘密。第一种方法的问题是,如果你提交了secret.yaml 文件,你就会暴露你的秘密,所以使用手动选项会更安全。只要确保秘密已经在Kubernetes中,否则Pod会崩溃。
我们要去挂载。
-
一个特定文件夹中的单个文件的名称。 非秘密的
-
特定文件夹中的所有文件,不对其命名。 秘密
-
应用根中的单个文件。 秘密
结构
secret 文件夹和.env 文件下的文件不被提交,因为它们有开发环境的秘密。
├── Makefile
├── config
│ └── finders.yaml
├── deploy
│ └── k8s
│ ├── configmap.yaml
│ ├── deployment.yaml
│ └── secret.yaml
├── docker
│ └── dev
│ └── Dockerfile
├── .env
├── .env.dist
├── .gitignore
├── main.go
└── secret
├── credentials.conf
└── keys.yaml
文件
制作文件
## Build application binary.
.PHONY: build
build:
go build -race -ldflags "-s -w" -o bin/main main.go
## Build application binary and run it.
.PHONY: run
run: build
bin/main
## -----------------------------------------------------------------------------------
## Build, tag and push application image to registry then clean up.
.PHONY: push
push:
docker build -t you/address-finder:latest -f docker/dev/Dockerfile .
docker push you/address-finder:latest
docker rmi you/address-finder:latest
docker system prune --volumes --force
## Deploy application to kubernetes cluster.
.PHONY: deploy
deploy:
# This secret command is not needed for manual secret interactions (preferred).
kubectl apply -f deploy/k8s/secret.yaml
kubectl apply -f deploy/k8s/configmap.yaml
kubectl apply -f deploy/k8s/deployment.yaml
.env
ENV_VAR_X=x_secret_from_repo_non_dist
ENV_VAR_Y=y_secret_from_repo_non_dist
ENV_VAR_Z=z_non_secret_from_repo_non_dist
.env.dist
ENV_VAR_X=x_secret_from_repo_dist
ENV_VAR_Y=y_secret_from_repo_dist
ENV_VAR_Z=z_non_secret_from_repo_dist
.gitignore
secret/
.env
.main.go
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"time"
"github.com/joho/godotenv"
)
func main() {
fmt.Println("--- Secret credentials file ---------------------")
scrConf, err := ioutil.ReadFile("secret/credentials.conf")
if err != nil {
log.Fatalln(err)
}
fmt.Println(string(scrConf))
fmt.Println("--- Secret keys file ----------------------------")
kysConf, err := ioutil.ReadFile("secret/keys.yaml")
if err != nil {
log.Fatalln(err)
}
fmt.Println(string(kysConf))
fmt.Println("--- Public finders file -------------------------")
finConf, err := ioutil.ReadFile("config/finders.yaml")
if err != nil {
log.Fatalln(err)
}
fmt.Println(string(finConf))
fmt.Println("--- System environment variables ----------------")
_ = godotenv.Load()
fmt.Println(value("ENV_VAR_X"))
fmt.Println(value("ENV_VAR_Y"))
fmt.Println(value("ENV_VAR_Z"))
time.Sleep(time.Hour)
}
func value(key string) string {
v, ok := os.LookupEnv(key)
if !ok {
log.Fatalf("the environment var %s was not found", key)
}
return v
}
Docker文件
#
# STAGE 1: build
#
FROM golang:1.15-alpine3.12 as build
WORKDIR /source
COPY . .
RUN CGO_ENABLED=0 go build -ldflags "-s -w" -o bin/main main.go
#
# STAGE 2: run
#
FROM alpine:3.12 as run
COPY --from=build /source/bin/main /main
ENTRYPOINT ["/main"]
finders.yaml
finders:
- name: postcode
api: https://api.postcodes.io/postcodes
method: GET
- name: ip
api: http://ip-api.com/json
method: GET
credentials.yaml
title: this is credentials.conf secret content (local)
line_1: hello (local)
line_2: world (local)
keys.yaml
KEY_1: key 1 (local)
KEY_2: key 2 (local)
configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: address-finder-configmap
data:
finders.yaml: |
finders:
- name: address
api: https://api.getAddress.io/find
method: GET
- name: postcode
api: https://api.postcodes.io/postcodes
method: GET
- name: ip
api: http://ip-api.com/json
method: GET
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: address-finder-deployment
labels:
app: address-finder
spec:
replicas: 1
selector:
matchLabels:
app: address-finder
template:
metadata:
labels:
app: address-finder
spec:
containers:
- name: golang
image: you/address-finder:latest
volumeMounts:
# Refers to a single file
- name: config
mountPath: ./config/finders.yaml
subPath: finders.yaml
readOnly: true
# Refers to all the secret files in a folder
- name: secret
mountPath: ./secret
readOnly: true
# Refers to single secret file to app root
- name: dotenv
mountPath: ./.env
subPath: .env # Without this, .env will be created as a folder, not a file!
readOnly: true
volumes:
- name: config
configMap:
name: address-finder-configmap
- name: secret
secret:
secretName: address-finder-secret
- name: dotenv
secret:
secretName: address-finder-secret
items:
- key: .env
path: ./.env
secret.yaml
记住这不是处理秘密的首选方式。你将删除这个文件并在选项2中用kubectl命令在Kubernetes集群中手动创建address-finder-secret 组件。你在这里看到的是选项1。
apiVersion: v1
kind: Secret
metadata:
name: address-finder-secret
type: Opaque
data:
credentials.conf: | # cat secret/credentials.conf | base64
dGl0bGU6IHRoaXMgaXMgY3JlZGVudGlhbHMuY29uZiBzZWNyZXQgY29udGVudCAobG9jYWwpCmxpbmVfMTogaGVsbG8gKGxvY2FsKQoKbGluZV8yOiB3b3JsZCAobG9jYWwpCg==
keys.yaml: | # cat secret/keys.yaml | base64
S0VZXzE6IGtleSAxIChsb2NhbCkKS0VZXzI6IGtleSAyIChsb2NhbCkK
.env: | # cat .env | base64
RU5WX1ZBUl9YPXhfc2VjcmV0X2Zyb21fcmVwb19ub25fZGlzdApFTlZfVkFSX1k9eV9zZWNyZXRfZnJvbV9yZXBvX25vbl9kaXN0CkVOVl9WQVJfWj16X25vbl9zZWNyZXRfZnJvbV9yZXBvX25vbl9kaXN0Cg==
本地测试
这是我们在本地环境下运行应用程序时终端输出的情况。正如你所看到的,内容与我们上面列出的文件相符。
$ make run
go build -race -ldflags "-s -w" -o bin/main main.go
bin/main
--- Secret credentials file ---------------------
title: this is credentials.conf secret content (local)
line_1: hello (local)
line_2: world (local)
--- Secret keys file ----------------------------
KEY_1: key 1 (local)
KEY_2: key 2 (local)
--- Public finders file -------------------------
finders:
- name: postcode
api: https://api.postcodes.io/postcodes
method: GET
- name: ip
api: http://ip-api.com/json
method: GET
--- System environment variables ----------------
x_secret_from_repo_non_dist
y_secret_from_repo_non_dist
z_non_secret_from_repo_non_dist
部署
选项1
在这种情况下,我们将secret.yaml ,并依靠它来自动创建秘密。**这不是首选!**部署下面的应用程序:
$ make deploy
# This secret command is not needed for manual secret interactions (preferred).
kubectl apply -f deploy/k8s/secret.yaml
secret/address-finder-secret created
kubectl apply -f deploy/k8s/configmap.yaml
configmap/address-finder-configmap created
kubectl apply -f deploy/k8s/deployment.yaml
deployment.apps/address-finder-deployment created
检查下面的应用程序日志。
$ kubectl logs pod/address-finder-deployment-7f6d6959db-w57gn
--- Secret credentials file ---------------------
title: this is credentials.conf secret content (local)
line_1: hello (local)
line_2: world (local)
--- Secret keys file ----------------------------
KEY_1: key 1 (local)
KEY_2: key 2 (local)
--- Public finders file -------------------------
finders:
- name: address
api: https://api.getAddress.io/find
method: GET
- name: postcode
api: https://api.postcodes.io/postcodes
method: GET
- name: ip
api: http://ip-api.com/json
method: GET
--- System environment variables ----------------
x_secret_from_repo_non_dist
y_secret_from_repo_non_dist
z_non_secret_from_repo_non_dist
正如你所看到的,秘密已经被解码(它们被编码为本地副本)并被安装在Pod中。另外,查找器的配置来自configmap.yaml 文件,而不是应用程序仓库。环境变量来自于.env 文件而不是环境,因为我们没有把它们作为普通的环境变量来创建。让我们检查一下Pod的内容:
$ kubectl exec -it pod/address-finder-deployment-7f6d6959db-w57gn sh
/ # ls -la
total 1816
-rw-r--r-- 1 root root 118 Nov 26 19:26 .env
drwxr-xr-x 2 root root 4096 Nov 26 19:26 config
drwxrwxrwt 3 root root 140 Nov 26 19:26 secret
...
/ # cat .env
ENV_VAR_X=x_secret_from_repo_non_dist
ENV_VAR_Y=y_secret_from_repo_non_dist
ENV_VAR_Z=z_non_secret_from_repo_non_dist
/ # ls -l config/
total 4
-rw-r--r-- 1 root root 223 Nov 26 19:26 finders.yaml
/ # cat config/finders.yaml
finders:
- name: address
api: https://api.getAddress.io/find
method: GET
- name: postcode
api: https://api.postcodes.io/postcodes
method: GET
- name: ip
api: http://ip-api.com/json
method: GET
/ # ls -l secret/
total 0
lrwxrwxrwx 1 root root 23 Nov 26 19:26 credentials.conf -> ..data/credentials.conf
lrwxrwxrwx 1 root root 16 Nov 26 19:26 keys.yaml -> ..data/keys.yaml
/ # cat secret/credentials.conf
title: this is credentials.conf secret content (local)
line_1: hello (local)
line_2: world (local)
/ # cat secret/keys.yaml
KEY_1: key 1 (local)
KEY_2: key 2 (local)
让我们检查一下秘密组件是什么样子的。我们将在后面的选项2中手动创建:
$ kubectl get secrets
NAME TYPE DATA AGE
address-finder-secret Opaque 3 10m
$ kubectl describe secret address-finder-secret
Name: address-finder-secret
Namespace: default
Labels:
Annotations:
Type: Opaque
Data
====
keys.yaml: 42 bytes
.env: 118 bytes
credentials.conf: 100 bytes
方案2
这就是我们根本没有secret.yaml ,而是依靠在部署前在Kubernetes中手动创建秘密--**首选!**这里我们手动创建秘密文件。我已经有了它们,所以只是展示了内容:
$ cat ./Desktop/credentials.conf
title: this is credentials.conf secret content (desktop)
line_1: hello (desktop)
line_2: world (dektop)
$ cat ./Desktop/keys.yaml
KEY_1: key 1 (desktop)
KEY_2: key 2 (desktop)
$ cat ./Desktop/.env
ENV_VAR_X=x_secret_from_desktop
ENV_VAR_Y=y_secret_from_desktop
ENV_VAR_Z=z_non_secret_from_desktop
让我们把这些文件变成Kubernetes的秘密组件:
$ kubectl create secret generic address-finder-secret --save-config \
> --from-file=./Desktop/credentials.conf \
> --from-file=./Desktop/keys.yaml \
> --from-file=./Desktop/.env
正如你在下面看到的,这个命令与之前在选项1中创建的secret.yaml :
$ kubectl get secrets
NAME TYPE DATA AGE
address-finder-secret Opaque 3 21s
$ kubectl describe secret address-finder-secret
Name: address-finder-secret
Namespace: default
Labels:
Annotations:
Type: Opaque
Data
====
.env: 101 bytes
credentials.conf: 105 bytes
keys.yaml: 47 bytes
现在我们来部署这个应用程序。我从make命令中删除了secret.yaml 命令:
$ make deploy
kubectl apply -f deploy/k8s/configmap.yaml
configmap/address-finder-configmap created
kubectl apply -f deploy/k8s/deployment.yaml
让我们看看应用程序的日志/输出,重点是秘密:
$ kubectl logs pod/address-finder-deployment-7f6d6959db-f4rcr
--- Secret credentials file ---------------------
title: this is credentials.conf secret content (desktop)
line_1: hello (desktop)
line_2: world (dektop)
--- Secret keys file ----------------------------
KEY_1: key 1 (desktop)
KEY_2: key 2 (desktop)
--- Public finders file -------------------------
finders:
- name: address
api: https://api.getAddress.io/find
method: GET
- name: postcode
api: https://api.postcodes.io/postcodes
method: GET
- name: ip
api: http://ip-api.com/json
method: GET
--- System environment variables ----------------
x_secret_from_desktop
y_secret_from_desktop
z_non_secret_from_desktop
正如你在上面看到的,它工作得很好。
如果你想在以后更新秘密,你可以使用kubectl edit secret address-finder-secret 命令。只要记住它需要base64编码的数据。
你可以使用下面的命令进行base64编码/解码:
// encode
$ cat {file-path} | base64
// decode
$ echo -n {plain-secret-goes-here} | base64