书籍来源:《CKA/CKAD应试指南:从Docker到Kubernetes完全攻略》
一边学习一边整理老师的课程内容及实验笔记,并与大家分享,侵权即删,谢谢支持!
附上汇总贴:CKA备考实验 | 汇总_热爱编程的通信人的博客-CSDN博客
secret的主要作用是存储密码信息,以及往pod里传递文件。secret以键值对的方式存储,格式如下。
键=值 或者是 key=value
其中这里的“值”不是以明文的方式存储的,而是通过base64编码过的,具体看下面的例子。
创建secret
创建secret的方法很多,可以直接指定key和value,也可以把一个文件的内容作为value,还可以直接写yaml文件,下面分别用不同的方法来创建。
为了区分前面章节创建的文件区分,这里单独创建一个目录secret,本章所需要的文件全部在目录secret里创建。
##########实操验证##########
[root@vms10 ~]# mkdir secret
[root@vms10 ~]# cd secret/
[root@vms10 secret]#
创建一个命名空间nssec,本章所有实验均在这个命名空间里操作。
##########实操验证##########
[root@vms10 secret]# kubectl create ns nssec
namespace/nssec created
[root@vms10 secret]# kubens nssec
Context "kubernetes-admin@kubernetes" modified.
Active namespace is "nssec".
[root@vms10 secret]#
查看当前命名空间里现存的secret。
##########实操验证##########
[root@vms10 secret]# kubectl get secret
NAME TYPE DATA AGE
default-token-cp9rm kubernetes.io/service-account-token 3 35s
[root@vms10 secret]#
创建secret有以下多种方法。
方法1:命令行的方式
语法:
kubectl create secret generic 名字 --from-literal=k1=v1 --from-literal=k2=v2 ...
这里k1的值为v1,k2的值为v2,如果需要多个变量,就写多个--from-literal。
步骤1:创建一个名字为mysecret1的secret。
##########实操验证##########
[root@vms10 secret]# kubectl create secret generic mysecret1 --from-literal=xx=tom --from-literal=yy=redhat
secret/mysecret1 created
[root@vms10 secret]#
步骤2:查看现有的secret。
##########实操验证##########
[root@vms10 secret]# kubectl get secrets
NAME TYPE DATA AGE
default-token-cp9rm kubernetes.io/service-account-token 3 2m49s
mysecret1 Opaque 2 92s
[root@vms10 secret]#
secret有三种类型。
(1)Opaque:base64编码格式的secret,用来存储密码、密钥等,但数据也通过base64-decode解码得到原始数据,加密型很弱。
(2)http://kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息。
(3)http://kubernetes.io/service-account-token:用于被serviceaccount引用。
创建serviceaccount时,kubernetes会默认创建对应的secret。pod如果使用了serviceaccount,对应的secret会自动挂裁到Pod目录/run/secrets/http://kubernetes.io/serviceaccount(后面有专门章节将serviceaccount)中。
步骤3:查看mysecret1的具体属性。
##########实操验证##########
[root@vms10 secret]# kubectl describe secrets mysecret1
Name: mysecret1
Namespace: nssec
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
xx: 3 bytes
yy: 6 bytes
[root@vms10 secret]#
这里可以看到mysecret1里有两个变量,分别是xx和yy,xx的值有3个字符,yy的值有6个字符,具体是什么这里看不出来。
步骤4:查看mysecret1的键值对。
##########实操验证##########
[root@vms10 secret]# kubectl get secret mysecret1 -o yaml
apiVersion: v1
data:
xx: dG9t
yy: cmVkaGF0
kind: Secret
metadata:
creationTimestamp: "2023-05-30T07:59:25Z"
name: mysecret1
namespace: nssec
resourceVersion: "38416"
selfLink: /api/v1/namespaces/nssec/secrets/mysecret1
uid: 67e180f5-136a-48be-9a56-49d18a3b919a
type: Opaque
[root@vms10 secret]#
上面data字段里列出来的就是mysecret1的键值对,其中xx和yy的值都是经过base64编码的,需要解码才能看到具体值。
步骤5:解码。
##########实操验证##########
[root@vms10 secret]# echo "dG9t" | base64 --decode
tom[root@vms10 secret]# echo "cmVkaGF0" | base64 --decode
redhat[root@vms10 secret]#
[root@vms10 secret]#
方法2:把文件创建为secret
也可以把一个文件创建为secret,此时文件的文件名作为key,文件的内容为value,如果要把一个文件创建为secret的话,使用的命令如下。
kubectl create secret generic mysecret2 --from-file=file1 --from-file=file2 ..
这种创建secret的作用是,把一个文件的内容写入secret里,后面通过卷的方式来引用这个secret,就可以把此文件写入pod里了。
步骤1:查看/etc/hosts的内容。
##########实操验证##########
[root@vms10 secret]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.110 vms10.rhce.cc vms10
192.168.1.111 vms11.rhce.cc vms11
192.168.1.112 vms12.rhce.cc vms12
[root@vms10 secret]#
这里文件名为hosts,现在要把这个文件创建为一个secret。
步骤2:创建secret。
##########实操验证##########
[root@vms10 secret]# kubectl create secret generic mysecret2 --from-file=/etc/hosts
secret/mysecret2 created
[root@vms10 secret]#
步骤3:下面查看这个secret的内容。
##########实操验证##########
[root@vms10 secret]# kubectl get secrets mysecret2 -o yaml
apiVersion: v1
data:
hosts: MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjEuMTEwICAgdm1zMTAucmhjZS5jYyAgICAgICAgICB2bXMxMAoxOTIuMTY4LjEuMTExICAgdm1zMTEucmhjZS5jYyAgICAgICAgICB2bXMxMQoxOTIuMTY4LjEuMTEyICAgdm1zMTIucmhjZS5jYyAgICAgICAgICB2bXMxMgo=
kind: Secret
metadata:
creationTimestamp: "2023-05-30T08:04:35Z"
name: mysecret2
namespace: nssec
resourceVersion: "39007"
selfLink: /api/v1/namespaces/nssec/secrets/mysecret2
uid: 22856070-7c5c-494e-9230-69a64fabf841
type: Opaque
[root@vms10 secret]#
这里hosts就是文件名,下面的值是hosts文件里的内容。这段内容也可以直接通过如下命令来获取。
##########实操验证##########
[root@vms10 secret]# kubectl get secrets mysecret2 -o jsonpath='{.data.hosts}'
MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjEuMTEwICAgdm1zMTAucmhjZS5jYyAgICAgICAgICB2bXMxMAoxOTIuMTY4LjEuMTExICAgdm1zMTEucmhjZS5jYyAgICAgICAgICB2bXMxMQoxOTIuMTY4LjEuMTEyICAgdm1zMTIucmhjZS5jYyAgICAgICAgICB2bXMxMgo=[root@vms10 secret]#
[root@vms10 secret]#
-o指的是输出的格式,这里以json格式输出,并获取data下hosts字段的值。
步骤4:解码。
上面这段输出通过管道传递给base64 -d后的结果是这样的。
##########实操验证##########
[root@vms10 secret]# kubectl get secrets mysecret2 -o jsonpath='{.data.hosts}' | base64 -d
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.110 vms10.rhce.cc vms10
192.168.1.111 vms11.rhce.cc vms11
192.168.1.112 vms12.rhce.cc vms12
[root@vms10 secret]#
可以看到这个就是hosts文件的内容。
步骤5:创建一个包含两个文件的secret mysecret3。
##########实操验证##########
[root@vms10 secret]# kubectl create secret generic mysecret3 --from-file=/etc/hosts --from-file=/etc/issue
secret/mysecret3 created
[root@vms10 secret]#
这个secret里包含了两个文件:/etc/hosts和/etc/issue,即mysecret3里有两个key,分别是hosts和issue,它们的值分别是/etc/hosts和/etc/issue的内容。
步骤6:获取mysecret3的键值对。
##########实操验证##########
[root@vms10 secret]# kubectl get secrets mysecret3 -o yaml
apiVersion: v1
data:
hosts: MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjEuMTEwICAgdm1zMTAucmhjZS5jYyAgICAgICAgICB2bXMxMAoxOTIuMTY4LjEuMTExICAgdm1zMTEucmhjZS5jYyAgICAgICAgICB2bXMxMQoxOTIuMTY4LjEuMTEyICAgdm1zMTIucmhjZS5jYyAgICAgICAgICB2bXMxMgo=
issue: XFMKS2VybmVsIFxyIG9uIGFuIFxtCgo=
kind: Secret
metadata:
creationTimestamp: "2023-05-30T08:07:54Z"
name: mysecret3
namespace: nssec
resourceVersion: "39387"
selfLink: /api/v1/namespaces/nssec/secrets/mysecret3
uid: c729f03e-4fcb-4b1b-bd99-d450cb9b35fb
type: Opaque
[root@vms10 secret]#
从上面可以看到两个键hosts和issue,以及它们对应的值,还可以通过如下命令分别获取其key的值。
##########实操验证##########
[root@vms10 secret]# kubectl get secrets mysecret3 -o jsonpath='{.data.hosts}'
MTI3LjAuMC4xICAgbG9jYWxob3N0IGxvY2FsaG9zdC5sb2NhbGRvbWFpbiBsb2NhbGhvc3Q0IGxvY2FsaG9zdDQubG9jYWxkb21haW40Cjo6MSAgICAgICAgIGxvY2FsaG9zdCBsb2NhbGhvc3QubG9jYWxkb21haW4gbG9jYWxob3N0NiBsb2NhbGhvc3Q2LmxvY2FsZG9tYWluNgoxOTIuMTY4LjEuMTEwICAgdm1zMTAucmhjZS5jYyAgICAgICAgICB2bXMxMAoxOTIuMTY4LjEuMTExICAgdm1zMTEucmhjZS5jYyAgICAgICAgICB2bXMxMQoxOTIuMTY4LjEuMTEyICAgdm1zMTIucmhjZS5jYyAgICAgICAgICB2bXMxMgo=[root@vms10 secret]#
[root@vms10 secret]# kubectl get secrets mysecret3 -o jsonpath='{.data.issue}'
XFMKS2VybmVsIFxyIG9uIGFuIFxtCgo=[root@vms10 secret]#
[root@vms10 secret]#
这种用法一般用在创建pod的时候给pod传递文件,后面讲解如何使用secret时会详细描述。
方法3:变量文件的方法
第3种创建secret的方法是,通过创建变量文件的方式创建一个文件,里面的格式为:
变量1=值1
变量2=值2
这种格式,等号前面的为key,等号后面的为value,看下面的例子。
步骤1:创建变量文件env.txt。
##########实操验证##########
[root@vms10 secret]# cat env.txt
xx=tom
yy=redhat
[root@vms10 secret]#
在env.txt里定义了两个变量xx和yy,其值分别为tom和redhat。
步骤2:创建secret。
##########实操验证##########
[root@vms10 secret]# kubectl create secret generic mysecret4 --from-env-file=env.txt
secret/mysecret4 created
[root@vms10 secret]#
方法4:通过yaml文件的方式
如同创建pod一样,可以写一个secret的yaml文件,然后通过kubectl apply来创建。下面的例子里将会创建一个名字为mysecret5的secret,里面包含两个键值对:xx=tom和yy=redhat。
步骤1:先求出两个值tom和redhat对应的base64编码之后的值。
##########实操验证##########
[root@vms10 secret]# echo -n 'tom' | base64
dG9t
[root@vms10 secret]# echo -n 'redhat' | base64
cmVkaGF0
[root@vms10 secret]#
步骤2:创建yaml文件。
##########实操验证##########
[root@vms10 secret]# cat secret5.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret5
type: Opaque
data:
xx: dG9t
yy: cmVkaGF0
[root@vms10 secret]#
步骤3:创建secret。
##########实操验证##########
[root@vms10 secret]# kubectl apply -f secret5.yaml
secret/mysecret5 created
[root@vms10 secret]# kubectl get secrets
NAME TYPE DATA AGE
default-token-cp9rm kubernetes.io/service-account-token 3 102m
mysecret1 Opaque 2 100m
mysecret2 Opaque 1 95m
mysecret3 Opaque 2 92m
mysecret4 Opaque 2 25m
mysecret5 Opaque 2 7s
[root@vms10 secret]#
步骤4:删除某secret。
##########实操验证##########
[root@vms10 secret]# kubectl delete secrets mysecret5
secret "mysecret5" deleted
[root@vms10 secret]#
使用secret
上面已经把secret创建出来了,那么如何在pod里使用这些secret呢?主要有两种方式来引用卷,即卷和变量的方式。
方法1:以卷的方式
这种方式主要是在pod的yaml文件里,创建一个类型为secret的卷,然后挂载到容器里某个指定的目录里,容器创建好之后,会在容器的挂载目录里创建一个文件,此文件的文件名为secret里的key,文件的内容为对应key的value。这种以卷的方式引用secret的主要作用是往pod里传递文件。
下面创建一个名字为pod1的pod,以卷的方式挂载mysecret2到容器的/etc/test目录里。
步骤1:创建pod的yaml文件。
##########实操验证##########
[root@vms10 secret]# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod1
name: pod1
spec:
volumes:
- name: xx
secret:
secretName: mysecret2
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod1
volumeMounts:
- name: xx
mountPath: "/etc/test"
status: {}
[root@vms10 secret]#
在这个yaml文件里创建了一个名字为xx、类型为secret的卷,使用mysecret2,在pod1里的容器里把xx这个卷挂载到/etc/test目录里。因为mysecret2有一个键hosts,值为文件/etc/hosts的内容(前面演示过),所以在容器/etc/test目录里有一个文件hosts,内容就是/etc/hosts的内容。
步骤2:创建此pod。
##########实操验证##########
[root@vms10 secret]# kubectl apply -f pod1.yaml
pod/pod1 created
[root@vms10 secret]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod1 1/1 Running 0 4s
[root@vms10 secret]#
步骤3:查看此pod里/etc/test有什么文件。
##########实操验证##########
[root@vms10 secret]# kubectl exec pod1 -- ls /etc/test
hosts
[root@vms10 secret]#
可以看到里面有一个文件hosts。
步骤4:查看这个文件的内容。
##########实操验证##########
[root@vms10 secret]# kubectl exec pod1 -- cat /etc/test/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.110 vms10.rhce.cc vms10
192.168.1.111 vms11.rhce.cc vms11
192.168.1.112 vms12.rhce.cc vms12
[root@vms10 secret]#
可以看到就是/etc/hosts的内容,删除此pod。
如果在上面pod1里定义volumes的时候,引用的是mysecret3(mysecret3里使用了两个文件),则在容器里的/etc/test里会创建两个文件:hosts和issue。但是如果使用mysecret3,不想把两个文件全部写入挂载点,只想使用一个文件的话,那怎么办?此时可以用subPath来解决这个问题。
步骤5:修改pod1.yaml,内容如下。
##########实操验证##########
[root@vms10 secret]# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod1
name: pod1
spec:
volumes:
- name: xx
secret:
secretName: mysecret3
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: pod1
volumeMounts:
- name: xx
mountPath: "/etc/test/issue"
subPath: issue
status: {}
[root@vms10 secret]#
这里创建一个卷xx,里面使用的是mysecret3,在容器里引用卷xx,这里比刚才多了一个subPath,即只引用issue这个文件。
subpath指定从secret里引用哪个文件,把这个文件写入/etc/test里,然后命名为issue。如果想命名为其他名字,比如filex,则mountPath的值应该写/etc/test/filex。如果mountPath的值只写为/etc/test的话,则是把issue写入/etc/里,然后命名为test,即/etc/test是一个文件,内容为issue的内容。
步骤6:查看容器里/etc/test的内容。
##########实操验证##########
[root@vms10 secret]# kubectl exec pod1 -- ls /etc/test
issue
[root@vms10 secret]#
可以看到此容器里只有一个文件hosts。
步骤7:查看/etc/test/hosts的内容。
##########实操验证##########
[root@vms10 secret]# kubectl exec pod1 -- cat /etc/test/issue
\S
Kernel \r on an \m
[root@vms10 secret]#
可以看到把/etc/issue的内容写入容器里了。
如果要修改服务的配置文件,比如nginx的配置文件,就可以不必重新编译镜像,只要把写好的一个nginx.conf创建为一个secret,然后在创建pod的时候,通过卷的方式就可以把新的配置文件写入pod里了。
方法2:以变量的方式
前面讲了,在定义pod的yaml文件的时候,如果想使用变量的话,格式为:
env:
- name: 变量名
value: 值
但是如果想从secret引用值的话,此处就不再写value了,而是写valueFrom,即从什么地方来引用这个变量的值,如下所示。
env:
- name: 变量名
valueFrom:
secretKeyRef:
name: secretX
key: keyX
意思是,变量的值将会使用secretX里的keyX这个键所对应的值。
前面创建mysecret1的时候,通过--from-literal=xx=tom --from-literral=yy=redhat创值了2个键值对,即xx=tom、yy=redhat。
下面创建一个mysql的pod,MYSQL_ROOT_PASSWORD这个变量的值不直接写在yaml文件里,而是引用mysecret1里的yy这个键的值。
步骤1:创建pod的yaml文件。
##########实操验证##########
[root@vms10 secret]# cat pod2.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod2
name: pod2
spec:
containers:
- image: hub.c.163.com/library/mysql:latest
imagePullPolicy: IfNotPresent
name: pod2
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret1
key: yy
[root@vms10 secret]#
此yaml文件是用于创建一个MySQL的pod,在创建容器时,需要指定一个变量MYSQL_ROOT_PASSWORD(用env下的name指定)。这个变量的值并没有直接用value写出来,而是用valueFrom从其他地方引用过来。这里通过secretKeyRef里的name引用mysecret1,然后通过key引用mysecret1里的yy这个键,整体的意思就是,MYSQL_ROOT_PASSWORD的值使用的是mysecret里yy这个键对应的值(为redhat)。
步骤2:创建pod并验证。
##########实操验证##########
[root@vms10 secret]# kubectl apply -f pod2.yaml
pod/pod2 created
[root@vms10 secret]# kubectl get pods
NAME READY STATUS RESTARTS AGE
pod2 1/1 Running 0 37s
[root@vms10 secret]#
步骤3:获取pod的IP。
##########实操验证##########
[root@vms10 secret]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod2 1/1 Running 0 60s 10.244.81.93 vms11.rhce.cc <none> <none>
[root@vms10 secret]#
步骤4:安装MariaDB,然后用root和密码redhat登录验证。
##########实操验证##########
[root@vms10 secret]# yum install -y mariadb
[root@vms10 secret]# mysql -uroot -predhat -h10.244.81.93
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.18 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
登录成功,说明密码引用成功。
自行删除此pod及刚创建的secret。