【k8s】kubernetes实战篇之创建密钥自动拉取私服镜像

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【k8s】kubernetes实战篇之创建密钥自动拉取私服镜像相关的知识,希望对你有一定的参考价值。

参考技术A docker login

https://docs.docker.com/engine/reference/commandline/login

使用Secret给容器传递敏感数据

https://zhuanlan.zhihu.com/p/357118382

kubernetes实战篇之创建密钥自动拉取私服镜像

https://www.cnblogs.com/tylerzhou/p/11112086.html

从私有仓库拉取镜像

https://kubernetes.io/zh/docs/tasks/configure-pod-container/pull-image-private-registry

文档 / 项目用户指南 / 配置 / 镜像仓库

https://kubesphere.io/zh/docs/project-user-guide/configuration/image-registry

Kubernetes 文档/概念/容器/镜像

https://kubernetes.io/zh/docs/concepts/containers/images/#using-a-private-registry

Kubernetes 文档/概念/配置/Secret

https://kubernetes.io/zh/docs/concepts/configuration/secret/#docker-config-secrets

运维实战 容器部分 Kubernetes存储

运维实战 容器部分 Kubernetes存储

CoinfigMap配置管理

K8S中, CoinfigMap被用于保存配置信息.

其主要特点是以键值对方式存储.

通过CoinfigMap, K8S提供了向Pod中导入配置的方法.

这一操作结局了镜像与配置耦合度高的问题, 实现了镜像与配置的解耦, 同时也大大提高了镜像的复用性和可移植性.

通过导入配置, 镜像可以批量化的进行配置修改和迁移.

可能的应用场景

  • 用于向容器内填充环境变量
  • 设置容器内的命令行参数
  • 作为容器内应用的配置文件存在
  • 填充数据卷的配置文件

如何使用

常见的创建ConfigMap的方式有4种

  • CLI交互式创建, 即字面值方式创建
  • 使用文件进行创建
  • 使用目录进行创建(实际就是批量文件创建)
  • 通过编写yaml资源清单创建

分类实践及其特性

字面值方式创建

##采用CLI方式交互式填写键值对
[root@Server2 YAML]# kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2
configmap/my-config created

##查看创建的ConfigMap
[root@Server2 YAML]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      5h31m
my-config          2      6s
[root@Server2 YAML]# kubectl describe cm my-config 
Name:         my-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
key1:
----
config1
key2:
----
config2
Events:  <none>

##测试完成后清理环境
[root@Server2 YAML]# kubectl delete cm my-config 
configmap "my-config" deleted

使用文件创建

默认情况下, 文件的名称会成为Key, 而文件的内容会成为对应的Value.

##使用DNS解析文件作为导入文件
[root@Server2 YAML]# kubectl create configmap my-config-2 --from-file=/etc/resolv.conf
configmap/my-config-2 created

##查看创建的ConfigMap
[root@Server2 YAML]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      5h32m
my-config-2        1      5s
[root@Server2 YAML]# kubectl describe cm my-config-2 
Name:         my-config-2
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
resolv.conf:
----

nameserver 114.114.114.114

Events:  <none>

##测试完成后清理环境
[root@Server2 YAML]# kubectl delete cm my-config-2 
configmap "my-config-2" deleted

使用目录创建

##创建测试目录并导入用于测试的文件
[root@Server2 mnt]# mkdir configMap
[root@Server2 mnt]# cd configMap/
[root@Server2 configMap]# cp /etc/passwd .
[root@Server2 configMap]# cp /etc/resolv.conf .
[root@Server2 configMap]# cp /etc/hosts .

##通过目录方式创建ConfigMap
[root@Server2 configMap]# kubectl create configmap my-config-3 --from-file=/etc/configMap

##查看创建的ConfigMap
[root@Server2 configMap]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      5h35m
[root@Server2 configMap]# kubectl create configmap my-config-3 --from-file=/mnt/configMap
configmap/my-config-3 created
[root@Server2 configMap]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      5h35m
my-config-3        3      3s
[root@Server2 configMap]# kubectl describe cm my-config-3 
Name:         my-config-3
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
hosts:
----
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.5.250 foundation4.ilt.example.com
172.25.5.1  Server1 reg.westos.org
172.25.5.2  Server2
172.25.5.3  Server3
172.25.5.4  Server4
172.25.5.5  Server5
172.25.5.6  Server6
172.25.5.7  Server7
172.25.5.8  Server8

passwd:
----
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
kubeadm:x:1000:1000::/home/kubeadm:/bin/bash

resolv.conf:
----

nameserver 114.114.114.114

Events:  <none>

##测试完成后清理环境
[root@Server2 configMap]# kubectl delete cm my-config-3 
configmap "my-config-3" deleted

使用资源清单创建

  • 使用的CM1.yaml文件内容
vim CM1.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: cm1-config
data:
  db_host: "172.25.0.250"
  db_port: "3306"
  • 创建一个简单的ConfigMap
[root@Server2 configMap]# vim CM1.yaml

##导入资源清单
[root@Server2 configMap]# kubectl apply -f CM1.yaml 
configmap/cm1-config created

##查看创建的ConfigMap
[root@Server2 configMap]# kubectl get cm
NAME               DATA   AGE
cm1-config         2      7s
kube-root-ca.crt   1      5h37m
[root@Server2 configMap]# kubectl describe cm cm1-config 
Name:         cm1-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
db_host:
----
172.25.0.250
db_port:
----
3306
Events:  <none>

如何使用ConfigMap

上文有提到, ConfigMap的用法之一就是导入Pod中, 那么如何在Pod中使用自然也有不同的用法了.

通过环境变量直接传递

  • Pod1.yaml内容
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
    - name: pod1
      image: busybox
      command: ["/bin/sh", "-c", "env"]
      env:
        - name: key1
          valueFrom:
            configMapKeyRef:
              name: cm1-config
              key: db_host
        - name: key2
          valueFrom:
            configMapKeyRef:
              name: cm1-config
              key: db_port
  restartPolicy: Never

实现目的

通过使用Pod1.yaml, 可以创建一个自主式Pod, 名称为pod1,并将cm1-config中的db_host赋给了容器内的环境变量key1, db_port的值赋给了key2, 在容器运行后采用终端输出环境变量.

相当于只是传递数值而并没有直接引入变量.

  • 验证效果
[root@Server2 configMap]# vim Pod1.yaml
[root@Server2 configMap]# kubectl apply -f Pod1.yaml 
pod/pod1 created
[root@Server2 configMap]# kubectl get pod
NAME   READY   STATUS              RESTARTS   AGE
pod1   0/1     ContainerCreating   0          6s
[root@Server2 configMap]# kubectl logs pod1 
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod1
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
key1=172.25.0.250
KUBERNETES_PORT_443_TCP_PROTO=tcp
key2=3306
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/

##进行环境清洁
[root@Server2 configMap]# kubectl delete -f Pod1.yaml 
pod "pod1" deleted

env命令的效果为打印环境变量.

上文代码框中的环境变量含有key1key2, 其内容取自ConfigMap的键.

另一种方式

当然, 也可以直接传递变量而不是赋值了.

  • Pod2.yaml内容
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  containers:
    - name: pod2
      image: busybox
      command: ["/bin/sh", "-c", "env"]
      envFrom:
        - configMapRef:
            name: cm1-config
  restartPolicy: Never
  • 检查结果
[root@Server2 configMap]# vim Pod2.yaml 
[root@Server2 configMap]# kubectl apply -f Pod2.yaml 
pod/pod2 created
[root@Server2 configMap]# kubectl get pod
NAME   READY   STATUS              RESTARTS   AGE
pod2   0/1     ContainerCreating   0          3s
[root@Server2 configMap]# kubectl logs pod2
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.96.0.1:443
HOSTNAME=pod2
SHLVL=1
db_port=3306
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/
db_host=172.25.0.250

[root@Server2 configMap]# kubectl delete -f Pod2.yaml 
pod "pod2" deleted

设置命令行参数方式

  • 修改过的Pod2.yaml内容
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
    - name: pod1
      image: busybox
      command: ["/bin/sh", "-c", "echo $(db_host) $(db_port)"]
      envFrom:
        - configMapRef:
            name: cm1-config
  restartPolicy: Never

不难看出, 这里是将变量的值在命令行中直接显示, 实际的实现与上面的方式并无二样.

[root@Server2 configMap]# vim Pod2.yaml 
[root@Server2 configMap]# kubectl apply -f Pod2.yaml 
pod/pod1 created
[root@Server2 configMap]# kubectl get pod
NAME   READY   STATUS              RESTARTS   AGE
pod1   0/1     ContainerCreating   0          3s
[root@Server2 configMap]# kubectl logs pod1 
172.25.0.250 3306

通过数据卷挂载进行使用

  • Pod3.yaml内容
apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  containers:
    - name: pod3
      image: busybox
      command: ["/bin/sh", "-c", "cat /config/db_host"]
      volumeMounts:
      - name: config-volume
        mountPath: /config
  volumes:
    - name: config-volume
      configMap:
        name: cm1-config
  restartPolicy: Never

上面的资源清单做了以下几件事:

  • cm1-config作为数据卷config-volume
  • config-volume挂载到/config
  • 在命令行中输出/config/db_host的内容, 实际就是读取了db_host的值
[root@Server2 configMap]# kubectl delete -f Pod2.yaml 
pod "pod1" deleted
[root@Server2 configMap]# kubectl apply -f Pod3.yaml 
pod/pod3 created
[root@Server2 configMap]# kubectl get pod
NAME   READY   STATUS      RESTARTS   AGE
pod3   0/1     Completed   0          10s
[root@Server2 configMap]# kubectl logs pod3 
172.25.0.250[root@Server2 configMap]# 

数据卷模式下的ConfigMap热更新

  • 通过以下实验, 我们可以验证ConfigMap热更新相关的问题
  • 通过以下YAML文件创建控制器并将配置文件作为数据卷挂载
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          ports:
          - containerPort: 80
          volumeMounts:
          - name: config-volume
            mountPath: /etc/nginx/conf.d
      volumes:
        - name: config-volume
          configMap:
            name: nginxconf
  • 使用的nginx.conf内容
server 
    listen	80;
    server_name	_;

    location / 
	root /usr/share/nginx/html;
	index  index.html index.htm;
    

  • 创建ConfigMap并进行内容检测
[root@Server2 configMap]# kubectl create configmap nginxconf --from-file=nginx.conf 
configmap/nginxconf created
[root@Server2 configMap]# kubectl get cm
kNAME               DATA   AGE
cm1-config         2      15m
kube-root-ca.crt   1      5h53m
nginxconf          1      10s
[root@Server2 configMap]# kubectl describe cm nginxconf 
Name:         nginxconf
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
nginx.conf:
----
server 
    listen       80;
    server_name  _;

    location / 
  root /usr/share/nginx/html;
  index  index.html index.htm;
    


Events:  <none>
  • 不难发现, 此时nginxconf中的nginx.conf的值中端口配置部分为listen 80
  • 创建控制器并进行内容检测
[root@Server2 configMap]# kubectl apply -f Pod4.yaml 
deployment.apps/my-nginx created
[root@Server2 configMap]# kubectl get pod
NAME                        READY   STATUS              RESTARTS   AGE
my-nginx-86d5ccb8db-zsl8v   0/1     ContainerCreating   0          5s
[root@Server2 configMap]# kubectl exec -it my-nginx-86d5ccb8db-zsl8v -- bash
root@my-nginx-86d5ccb8db-zsl8v:/# cd /etc/nginx/conf.d/
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# ls
nginx.conf
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# cat nginx.conf 
server 
    listen	80;
    server_name	_;

    location / 
	root /usr/share/nginx/html;
	index  index.html index.htm;
    


##查看容器内挂载情况(此处节选有用部份)
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# mount
/dev/mapper/rhel-root on /etc/nginx/conf.d type xfs (ro,relatime,attr2,inode64,noquota)
root@my-nginx-86d5ccb8db-zsl8v:/etc/nginx/conf.d# exit
exit
  • 测试Nginx服务情况, 通过默认80端口可以访问
[root@Server2 configMap]# kubectl get pod -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
my-nginx-86d5ccb8db-zsl8v   1/1     Running   0          94s   10.244.141.201   server3   <none>           <none>
[root@Server2 configMap]# curl 10.244.141.201
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body 
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

  • 修改nginxconf中的监听端口部分
[root@Server2 configMap]# kubectl edit cm nginxconf 
configmap/nginxconf edited
[root@Server2 configMap]# kubectl exec -it my-nginx-86d5ccb8db-zsl8v -- bash
root@my-nginx-86d5ccb8db-zsl8v:/# cat /etc/nginx/conf.d/nginx.conf 
server 
    listen	80;
    server_name	_;

    location / 
	root /usr/share/nginx/html;
	index  index.html index.htm;
    

root@my-nginx-86d5ccb8db-zsl8v:/# cat /etc/nginx/conf.d/nginx.conf 
server 
    listen	8000;
    server_name	_;

    location / 
	root /usr/share/nginx/html;
	index  index.html index.htm;
    

  • 等待一段时间后, 会发现容器内的文件内容也变化了, 即完成了文件的热更新
  • 但是稍加测试就会发现, 文件修改了, 服务却没有重载, 访问依旧是80端口而不没有变成8000端口
[root@Server2 configMap]# curl 10.244.141.201
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body 
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

[root@Server2 configMap]# curl 10.244.141.201:8000
curl: (7) Failed connect to 10.244.141.201:8000; Connection refused
  • 服务重载的正确方式: 打补丁
kubectl patch deployments.apps my-nginx --patch '"spec": "template":"metadata": "annotations": "version/config": "2021051102"'
deployment.apps/my-nginx patched
  • 在进行patch后, 80端口无法正常访问而8000畅通
[root@Server2 configMap]# curl 10.244.22.5
curl: (7) Failed connect to 10.244.22.5:80; Connection refused
[root@Server2 configMap]# curl 10.244.22.5:8000
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body 
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
  • 尝试修改回去
[root@Server2 configMap]# kubectl edit cm nginxconf 
configmap/nginxconf edited
[root@Server2 configMap]# kubectl patch deployments.apps my-nginx --patch '"spec": "template":"metadata": "annotations": "version/config": "2021051101"'
deployment.apps/my-nginx patched
[root@Server2 configMap]# kubectl get pod -o wide
NAME                        READY   STATUS        RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
my-nginx-687ccbd4f6-79cr9   1/1     Terminating   0          88s   10.244.22.5      server4   <none>           <none>
my-nginx-759cdbfbdc-f6jx8   1/1     Running       0          4s    10.244.141.202   server3   <none>           <none>
[root@Server2 configMap]# kubectl get pod -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE      NOMINATED NODE   READINESS GATES
my-nginx-759cdbfbdc-f6jx8   1/1     Running   0          6s    10.244.141.202   server3   <none>           <none>

[root@Server2 configMap]# curl 10.244.141.202
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body 
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
  • 不难发现, 提交补丁的过程实际上就是控制器完成了一次滚动更新的操作

Secret配置管理

简单概念

  • ConfigMap类似, Secret也是一种对象存储, 区别在于Secret对象性质的卷常被用来保存敏感信息, 如密码/OAuth认证令牌等等
  • 比起CpnfigMap, 将这些信息存储在Secret重命更加安全和灵活

常见的两种使用方式

  • 作为数据卷中的文件挂载入Pod进行使用
  • 当作Pod从私有仓库拉取镜像时的认证必需品使用

Secret的类型

类型定义
Service AccountK8S会自动创建包含访问 API 凭据的Secret, 并自动修改 pod 以使用此类型的Secret, 如果没有API凭证则Pod无法与管理节点交互
Opaque使用base64编码存储信息, 可以通过base64 --decode解码获得原始数据, 因此安全性弱, 常用于文件挂载入Pod时使用
kubernetes.io/dockerconfigjson用于存储Docker Registry的认证信息, 当需要拉取私有仓库的镜像时使用

Service Account的默认设置

  • Service Account创建时Kubernetes会默认创建对应的Secret

  • 对应的Secret会自动挂载到Pod/run/secrets/kubernetes.io/serviceaccount目录中

通过describe方式可以查看Pod挂载情况

kubectl describe pod my-nginx-759cdbfbdc-f6jx8

可以看到, Mounts信息中有Service Account, 挂载位置为/var/run/secrets/kubernetes.io/serviceaccount

进入容器查看其内部内容, 可以看到包含命名空间, CA证书, token

[root@Server2 ~]# kubectl exec my-nginx-759cdbfbdc-f6jx8 -- ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token

每个Namespace下有一个名为default的默认的Service Account对象

上方在内部文件中看到的token起到的作用时, 当Pod启动后用来协助完成Pod中的进程访问API Server时的身份鉴权过程

也就是说, 缺少了这部分文件, Pod将无法有效的与MASTER节点进行交互

Opaque Secret

交互式方式此处不列举, 但有一条需要注意的

  • 如果密码具有特殊字符, 则需要使用\\字符对其进行转义

文件方式创建

[root@Server2 Secret]# echo -n 'westos' > ./Password.txt
[root@Server2 Secret]# echo -n 'NeuWings' > ./Username.txt
[root@Server2 Secret]# ls
Password.txt  Username.txt
[root@Server2 Secret]# kubectl create secret generic db-user-pass --from-file=./Username.txt --from-file=./Password.txt 
secret/db-user-pass created
[root@Server2 Secret]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      13s
default-token-5rnvk   kubernetes.io/service-account-token   3      22h

同时可看到了上文所述的default

资源清单方式创建

  • 获取编码转化文字内容的方式
echo -n 'admin' | base64
YWRtaW4=
$ echo -n 'westos' | base64
d2VzdG9z
  • 使用的Mysecret.yaml内容
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: d2VzdG9z
  • 操作过程
[root@Server2 Secret]# vim Mysecret.yaml
[root@Server2 Secret]# kubectl delete secrets db-user-pass 
secret "db-user-pass" deleted
[root@Server2 Secret]# kubectl apply -f Mysecret.yaml 
secret/mysecret created
[root@Server2 Secret]# kubectl get secrets 
NAME                  TYPE                                  DATA   AGE
default-token-5rnvk   kubernetes.io/service-account-token   3      23h
mysecret              Opaque                                2      15s

默认情况下kubectl getkubectl describe为了安全是不会显示密码的内容, 只会显示长度

[root@Server2 Secret]# kubectl describe secrets mysecret 
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  6 bytes
username:  5 bytes

如果需要查看内容可以附加-o yaml参数, 使其以yaml格式输出.

将Secret挂载到Volume

  • 修改后的Mysecret.yaml内容
apiVersion: v1
kind: Pod
metadata:
  name: mysecret
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: secrets
      mountPath: "/secret"
      readOnly: true
  volumes:
  - name: secrets
    secret:
      secretName: mysecret
  • 操作记录
[root@Server2 Secret]# vim Mysecret.yaml
[root@Server2 Secret]# kubectl apply -f Mysecret.yaml
pod/mysecret created
[root@Server2 Secret]# kubectl get pod
NAME                        READY   STATUS              RESTARTS   AGE
my-nginx-759cdbfbdc-f6jx8   1/1     Running             1          17h
mysecret                    0/1     ContainerCreating   0          5s
[root@Server2 Secret]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
my-nginx-759cdbfbdc-f6jx8   1/1     Running   1          17h
mysecret                    1/1     Running   0          8s

向指定路径映射Secret密钥

  • 使用到的v2.yaml文件内容
apiVersion: v1
kind: Pod
metadata:
  name: mysecret
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: secrets
      mountPath: "/secret"
      readOnly: true
  volumes:
  - name: secrets
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
  • 操作流程
[root@Server2 Secret]# kubectl apply -f v2.yaml 
pod/mysecret created
[root@Server2 Secret]# kubectl get pod
NAME                        READY   STATUS              RESTARTS   AGE
my-nginx-759cdbfbdc-f6jx8   1/1     Running             1          17h
mysecret                    0/1     ContainerCreating   0          5s
[root@Server2 Secret]# kubectl describe pod mysecret 

将Secret设置为环境变量

  • 使用到的v3.yaml文件内容
apiVersion: v1
kind: Pod
metadata:
  name: secret-env
spec:
  containers:
  - name: nginx
    image: nginx
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret
            key: password

上面的资源清单做到了

  • mysecret中分别读取两个key对应的value存储到两个对应的环境变量中

环境变量读取Secret是一种很方便好用的方法, 但是其无法动态更新Secret

存储Docker Registry的认证信息

  • 创建一个包含私有仓库认证信息的Secret, 并创建对应的私有仓库
[root@Server2 Secret]# kubectl create secret docker-registry myregistrykey --docker-server=reg.westos.org --docker-username=admin --docker-password=westos --docker-email=lunarlibrary@foxmail.com
secret/myregistrykey created

  • 实验开始前私有仓库westos的日志情况

  • 实验用到的TestPod.yaml文件内容
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: game2048
      image: reg.westos.org/westos/game2048
  • 由于镜像拖取是从私有仓库, 而上面的资源清单没有做登陆验证, 镜像是无法拉取的
[root@Server2 Secret]# vim TestPod.yaml
[root@Server2 Secret]# kubectl apply -f TestPod.yaml 
pod/mypod created
[root@Server2 Secret]# kubectl get pod
NAME                        READY   STATUS             RESTARTS   AGE
my-nginx-759cdbfbdc-f6jx8   1/1     Running            1          17h
mypod                       0/1     ImagePullBackOff   0          4s
mysecret                    1/1     Running            0          9m46s
secret-env                  1/1     Running            0          6m38s
  • 修改构建, 增加imagePullSecrets
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: game2048
      image: reg.westos.org/westos/game2048
  imagePullSecrets:
    - name: myregistrykey
[root@Server2 Secret]# vim TestPod.yaml 
[root@Server2 Secret]# kubectl apply -f TestPod.yaml 
pod/game2048 created
[root@Server2 Secret]# kubectl get pod
NAME                        READY   STATUS    RESTARTS   AGE
game2048                    1/1     Running   0          6s
my-nginx-759cdbfbdc-f6jx8   1/1     Running   1          17h
mysecret                    1/1     Running   0          13m
secret-env                  1/1     Running   0          9m58s
  • 查看私有仓库日志, 可以看到一条登录后的pull, 证明mypod确实用到了引入的认证

Volumes配置管理

  • 默认情况下, 容器中的文件是临时存放在磁盘上的
  • 如果容器崩溃, kubelet将尝试重启容器, 容器重建后恢复初始状态, 而这将导致容器内的文件丢失
  • 而且在生产环境中, 一个Pod内经常存在多个容器, 各个容器间还需要共享文件/资源

这些问题该如何解决

K8S中的卷具有明确的生命周期, 与包裹它的Pod相同.

这也就意味着, 卷比Pod中运行的任何容器的存活时间都要长.这样即使容器重建, 数据也不会丢失.

当然, 如果Pod被摧毁, 卷自然也就不复存在了.

卷不能挂载到其他卷, 也不能与其他卷有硬链接. Pod 中的每个容器必须独立地指定每个卷的挂载位置.

emptyDir卷