第五周 -kubernetes(三)

本贴最后更新于 816 天前,其中的信息可能已经东海扬尘

一、实现基于 velero 对 etcd 的单独 namespace 的备份和恢复

Velero 简介

  • Velero 是 VMware 开源的云原生的灾难恢复和迁移工具,本身是开源的,采用 Go 语言编写,开源安全的备份、恢复和迁移 kubernetes 集群资源数据,https://velero.io/
  • Velero 支持标准的 k8s 集群,既可以是私有云平台,也可以是公有云平台,除了灾备之外还能做资源迁移,支持把容器应用从一个集群迁移到另一个集群。
  • Velero 的工作方式就是把 k8s 中数据备份到数据存储以实现高可用和持久化,默认备份保存时间为 720 小时,并在需要的时候进行下载和恢复。

Velero 与 etcd 快照备份区别

  • etcd 快照是全局备份,在即使一个资源对象需要恢复,也需要做全局恢复到备份状态,会影响其它 namespace 中 pod 运行服务。
  • Velero 可以针对性的备份,比如按照 namespace 单独备份、只备份单独的资源对象等,在恢复的时候只恢复单独 namespace 或资源对象,而不影响其它 namespace 中 pod 运行服务。
  • Velero 支持 ceph、oss 等对象存储,etcd 快照是本地文件。
  • Velero 支持任务计划实现周期备份,但 etcd 快照也可基于 cronjob 实现。

Velero 备份流程

  1. Velero 客户端调用 kubernetes API Server 创建 Backup 任务
  2. Backup 控制器基于 watch 机制通过 API Server 获取备份任务
  3. Backup 控制器开始执行备份动作,其会通过请求 API Server 获取需要备份的数据
  4. Backup 控制器将获取到的数据备份到指定的对象存储 server 端

准备存储环境

1. 部署 minio

位部署服务器(10.0.0.8)

  • 安装 docker

    安装方法见上一节 siyuan://blocks/20230117185040-38eg2ps

  • 部署 minio

    # 下载minio镜像,打tag,上传至本地harbor仓库 docker pull minio/minio:RELEASE.2022-12-12T19-27-27Z docker tag minio/minio:RELEASE.2022-12-12T19-27-27Z harbor.chu.net/baseimages/minio:2022-12-12T19-27-27Z docker push harbor.chu.net/baseimages/minio:2022-12-12T19-27-27Z # 创建数据目录 mkdir -p /data/minio # 创建minio容器,如果不指定,则默认用户名与密码为minioadmin/minioadmin,可通过环境自定义 docker run --name minio \ -p 9000:9000 \ -p 9999:9999 \ -d --restart=always \ -e "MINIO_ROOT_USER=admin" \ -e "MINIO_ROOT_PASSWORD=12345678" \ -v /data/minio/data:/data \ harbor.chu.net/baseimages/minio:2022-12-12T19-27-27Z server /data \ --console-address '0.0.0.0:9999'

2. 创建 bucket

  • 登录 web 界面

用户名:admin,密码:12345678

image

  • 进入管理页面

image

  • 创建 bucket

image

  • 验证 bucket

image

部署 velero

位 master1 节点部署

1. 下载 velero

https://github.com/vmware-tanzu/velero/releases

# 下载并解压 cd /usr/local/src #wget https://github.com/vmware-tanzu/velero/releases/download/v1.8.1/velero-v1.8.1-linux-amd64.tar.gz #tar xvf velero-v1.8.1-linux-amd64.tar.gz wget https://github.com/vmware-tanzu/velero/releases/download/v1.9.4/velero-v1.9.4-linux-amd64.tar.gz tar xvf velero-v1.9.4-linux-amd64.tar.gz cp velero-v1.9.4-linux-amd64/velero /usr/local/bin/

查看 velero 说明

[root@k8s-master1 src]#velero -h Velero is a tool for managing disaster recovery, specifically for Kubernetes cluster resources. It provides a simple, configurable, and operationally robust way to back up your application state and associated data. If you're familiar with kubectl, Velero supports a similar model, allowing you to execute commands such as 'velero get backup' and 'velero create schedule'. The same operations can also be performed as 'velero backup get' and 'velero schedule create'. Usage: velero [command] Available Commands: backup Work with backups backup-location Work with backup storage locations bug Report a Velero bug client Velero client related commands completion Generate completion script create Create velero resources debug Generate debug bundle delete Delete velero resources describe Describe velero resources get Get velero resources help Help about any command install Install Velero plugin Work with plugins restic Work with restic restore Work with restores schedule Work with schedules snapshot-location Work with snapshot locations uninstall Uninstall Velero version Print the velero version and associated image Flags: --add_dir_header If true, adds the file directory to the header --alsologtostderr log to standard error as well as files --colorized optionalBool Show colored output in TTY. Overrides 'colorized' value from $HOME/.config/velero/config.json if present. Enabled by default --features stringArray Comma-separated list of features to enable for this Velero process. Combines with values from $HOME/.config/velero/config.json if present -h, --help help for velero --kubeconfig string Path to the kubeconfig file to use to talk to the Kubernetes apiserver. If unset, try the environment variable KUBECONFIG, as well as in-cluster configuration --kubecontext string The context to use to talk to the Kubernetes apiserver. If unset defaults to whatever your current-context is (kubectl config current-context) --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) --log_dir string If non-empty, write log files in this directory --log_file string If non-empty, use this log file --log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) --logtostderr log to standard error instead of files (default true) -n, --namespace string The namespace in which Velero should operate (default "velero") --skip_headers If true, avoid header prefixes in the log messages --skip_log_headers If true, avoid headers when opening log files --stderrthreshold severity logs at or above this threshold go to stderr (default 2) -v, --v Level number for the log level verbosity --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging Use "velero [command] --help" for more information about a command.

2. 准备 velero 认证环境

# 创建工作目录 mkdir -p /data/velero cd /data/velero # 访问minio的认证文件,minio用户名与配置 cat >> velero-auth.txt <<EOF [default] aws_access_key_id = admin aws_secret_access_key = 12345678 EOF # 准备user-csr文件,用于访问k8s;也可直接使用/root/.kube/config文件 cat >>awsuser-csr.json <<EOF { "CN": "awsuser", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF # 准备证书签发环境 ## 1. 从部署服务器复制 scp 10.0.0.8:/etc/kubeasz/bin/cfssl* /usr/local/bin/ ## 2. 或者自行下载 apt install -y golang-cfssl wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl_1.6.1_linux_amd64 wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssljson_1.6.1_linux_amd64 wget https://github.com/cloudflare/cfssl/releases/download/v1.6.1/cfssl-certinfo_1.6.1_linux_amd64 mv cfssl-certinfo_1.6.1_linux_amd64 cfssl-certinfo mv cfssl_1.6.1_linux_amd64 cfssl mv cfssljson_1.6.1_linux_amd64 cfssljson cp cfssl-certinfo cfssl cfssljson /usr/local/bin/ chmod a+x /usr/local/bin/cfssl*

查看 cfssl 说明

[root@k8s-master1 velero]#cfssl -h Usage: Available commands: bundle certinfo serve ocspserve crl version gencert selfsign sign genkey scan print-defaults revoke gencsr gencrl ocspdump ocsprefresh ocspsign info Top-level flags: -alsologtostderr log to standard error as well as files -log_backtrace_at value when logging hits line file:N, emit a stack trace -log_dir string If non-empty, write log files in this directory -logtostderr log to standard error instead of files -stderrthreshold value logs at or above this threshold go to stderr -v value log level for V logs -vmodule value comma-separated list of pattern=N settings for file-filtered logging

3. 签发证书

cd /data/velero # 从部署服务器复制ca-config.json文件 scp 10.0.0.8:/etc/kubeasz/clusters/k8s-cluster1/ssl/ca-config.json /data/velero/ca-config.json # 执行证书签发 /usr/local/bin/cfssl gencert \ -ca=/etc/kubernetes/ssl/ca.pem \ -ca-key=/etc/kubernetes/ssl/ca-key.pem \ -config=./ca-config.json \ -profile=kubernetes \ ./awsuser-csr.json | cfssljson -bare awsuser

验证证书

[root@k8s-master1 velero]#ls awsuser-csr.json awsuser-key.pem awsuser.csr awsuser.pem ca-config.json velero-auth.txt

4. 配置客户端认证

#分发证书到api-server证书路径 cp awsuser-key.pem /etc/kubernetes/ssl/ cp awsuser.pem /etc/kubernetes/ssl/ #生成集群认证config文件 export KUBE_APISERVER="https://10.0.0.10:6443" kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=./awsuser.kubeconfig #设置客户端证书认证 kubectl config set-credentials awsuser \ --client-certificate=/etc/kubernetes/ssl/awsuser.pem \ --client-key=/etc/kubernetes/ssl/awsuser-key.pem \ --embed-certs=true \ --kubeconfig=./awsuser.kubeconfig #设置上下文参数 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=awsuser \ --namespace=velero-system \ --kubeconfig=./awsuser.kubeconfig #设置默认上下文 kubectl config use-context kubernetes --kubeconfig=awsuser.kubeconfig

查看 awsuser.kubeconfig​文件

[root@k8s-master1 velero]#cat awsuser.kubeconfig apiVersion: v1 clusters: - cluster: certificate-authority-data: LS0tLS1CRUdJTVRRek9EQXdXaGdQTNW1M...SXdRRERU5EIENFUlRJRklDQVRFLS0tLS0K server: https://10.0.0.10:6443 name: kubernetes contexts: - context: cluster: kubernetes namespace: velero-system user: awsuser name: kubernetes current-context: kubernetes kind: Config preferences: {} users: - name: awsuser user: client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0...tLS0tCk1JSUS0tLS0tCg== client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSh5...FdkMkNSCm5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==

5. 创建用户

#k8s集群中创建awsuser账户 kubectl create clusterrolebinding awsuser --clusterrole=cluster-admin --user=awsuser #创建namespace kubectl create ns velero-system

6. 安装 velero

# 执行安装 velero --kubeconfig ./awsuser.kubeconfig \ #连接k8s认证文件 install \ #安装 --provider aws \ #连接k8s用户 --plugins velero/velero-plugin-for-aws:v1.3.1 \ #velero镜像 --bucket velerodata \ #minio bucket名称 --secret-file ./velero-auth.txt \ #连接minio认证文件 --use-volume-snapshots=false \ #是否使用快照 --namespace velero-system \ #namespace名称 --backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://10.0.0.8:9000 #minio地址 velero --kubeconfig ./awsuser.kubeconfig \ install \ --provider aws \ --plugins velero/velero-plugin-for-aws:v1.3.1 \ --bucket velerodata \ --secret-file ./velero-auth.txt \ --use-volume-snapshots=false \ --namespace velero-system \ --backup-location-config region=minio,s3ForcePathStyle="true",s3Url=http://10.0.0.8:9000

验证

#验证安装 ## 查看pod状态 [root@k8s-master1 velero]#kubectl get pod -n velero-system NAME READY STATUS RESTARTS AGE velero-58d44fc999-gc9dd 0/1 Pending 0 61s ## 查看pod安装状态 [root@k8s-master1 velero]#kubectl describe pod velero-58d44fc999-gc9dd -n velero-system ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 4m13s default-scheduler 0/6 nodes are available: 6 node(s) had untolerated taint {node.kubernetes.io/unschedulable: }, 6 node(s) were unschedulable. preemption: 0/6 nodes are available: 6 Preemption is not helpful for scheduling. Normal Scheduled 70s default-scheduler Successfully assigned velero-system/velero-58d44fc999-gc9dd to 10.0.0.41 Normal Pulling 69s kubelet Pulling image "velero/velero-plugin-for-aws:v1.3.1" Normal Pulled 55s kubelet Successfully pulled image "velero/velero-plugin-for-aws:v1.3.1" in 14.121223331s Normal Created 55s kubelet Created container velero-velero-plugin-for-aws Normal Started 55s kubelet Started container velero-velero-plugin-for-aws Normal Pulling 54s kubelet Pulling image "velero/velero:v1.9.4" [root@k8s-master1 velero]#kubectl get pod -n velero-system NAME READY STATUS RESTARTS AGE velero-58d44fc999-gc9dd 1/1 Running 0 6m22s ## 查看logs确认正常启动,状态为valid [root@k8s-master1 velero]#kubectl logs velero-58d44fc999-gc9dd -n velero-system ... level=info msg="BackupStorageLocations is valid, marking as available" backup-storage-location=velero-system/default controller=backup-storage-location logSource="pkg/controller/backup_storage_location_controller.go:116"

备份

# 按当前日前对myserver namespace进行备份 DATE=`date +%Y%m%d%H%M%S` velero backup create myserver-ns-backup-${DATE} \ --include-namespaces myserver \ --kubeconfig=/data/velero/awsuser.kubeconfig \ --namespace velero-system

查看备份

image

备份指定资源对象

#备份指定namespace中pod或特定资源 velero backup create pod-backup-01 \ --include-cluster-resources=true \ --ordered-resources 'pods=myserver/net-test1,default/net-test1' \ --namespace velero-system \ --include-namespaces=myserver,default

批量备份所有 namespace

#!/bin/bash DATE=`date +%Y%m%d%H%M%S` NS_NAME=`kubectl get ns|awk 'NR>1{print $1}'` for NAME in ${NS_NAME};do velero backup create ${NAME}-ns-backup-${DATE} \ --include-namespaces ${NAME} \ --kubeconfig=/data/velero/awsuser.kubeconfig \ --namespace velero-system done

恢复

  • 删除数据
[root@k8s-master1 velero]#kubectl delete pod net-test1 -n myserver pod "net-test1" deleted [root@k8s-master1 velero]#kubectl delete pod net-test4 -n myserver pod "net-test4" deleted [root@k8s-master1 velero]#kubectl delete pod net-test5 -n myserver pod "net-test5" deleted [root@k8s-master1 velero]#kubectl get pod -n myserver NAME READY STATUS RESTARTS AGE net-test2 1/1 Running 7 (111m ago) 5d3h net-test3 1/1 Running 8 (111m ago) 5d3h net-test6 1/1 Running 7 (111m ago) 5d3h net-test7 1/1 Running 7 (111m ago) 5d3h net-test8 1/1 Running 8 (111m ago) 5d3h
  • 执行恢复
velero restore create --from-backup myserver-ns-backup-20230125003851 --wait \ --kubeconfig=/data/velero/awsuser.kubeconfig \ --namespace velero-system
  • 验证恢复
# pod恢复正常 [root@k8s-master1 velero]#kubectl get pod -n myserver NAME READY STATUS RESTARTS AGE net-test1 1/1 Running 0 20s net-test2 1/1 Running 7 (112m ago) 5d3h net-test3 1/1 Running 8 (113m ago) 5d3h net-test4 1/1 Running 0 20s net-test5 1/1 Running 0 20s net-test6 1/1 Running 7 (112m ago) 5d3h net-test7 1/1 Running 7 (112m ago) 5d3h net-test8 1/1 Running 8 (113m ago) 5d3h # 网络测试正常 [root@k8s-master1 velero]#kubectl exec -it net-test4 -n myserver sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. / # ping www.baidu.com PING www.baidu.com (183.232.231.172): 56 data bytes 64 bytes from 183.232.231.172: seq=0 ttl=127 time=82.630 ms 64 bytes from 183.232.231.172: seq=1 ttl=127 time=67.564 ms

二、掌握 k8s 中常见的资源对象的使用

k8s 常用资源对象有 deployment、service、configmap、secret

Deployment

https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/

https://cloud.google.com/kubernetes-engine/docs/concepts/deployment?hl=zh-cn

​Deployment 指不具有唯一标识的一组多个相同的 Pod。Deployment 运行应用的多个副本,并自动替换任何失败或无响应的实例。通过这种方式,Deployment 可帮助确保应用的一个或多个实例可用于处理用户请求。Deployment 由 Kubernetes Deployment 控制器管理。

​Deployment 使用 Pod 模板,此模板包含适用于其 Pod 的规范。Pod 规范确定每个 Pod 的外观:应在其容器内运行的应用、Pod 应装载的卷及其标签等。

Deployment 的 Pod 模板更改时,系统会自动创建新 Pod,每次创建一个。

1. 应用场景

Deployment 非常适合使用在多个副本上挂载的 ReadOnlyMany 或 ReadWriteMany 卷的无状态应用,但不适合使用 ReadWriteOnce 卷的工作负载。如果是使用 ReadWriteOnce 卷的有状态应用,请使用 StatefulSet。StatefulSet 旨在用于部署有状态应用和将数据保存到永久性存储空间(例如 Compute Engine 永久性磁盘)的聚簇应用。StatefulSet 适合部署 Kafka、MySQL、Redis、ZooKeeper 以及其他需要唯一持久身份和稳定主机名的应用。

Deployment 典型的应用场景包括:

  • 创建 Deployment 以 ReplicaSet 上线。ReplicaSet 在后台创建 Pod。 检查 ReplicaSet 的上线状态,查看其是否成功。
  • 通过更新 Deployment 的 Pod 模板规范,声明 Pod 新状态 。 新的 ReplicaSet 会被创建,Deployment 以受控速率将 Pod 从旧 ReplicaSet 迁移到新 ReplicaSet。 每个新的 ReplicaSet 都会更新 Deployment 的修订版本。
  • 如果 Deployment 的当前状态不稳定,回滚到较早的 Deployment 版本。 每次回滚都会更新 Deployment 的修订版本。
  • 扩大 Deployment 规模以承担更多负载。
  • 暂停 Deployment 的上线 以应用对 PodTemplateSpec 所作的多项修改, 然后恢复其执行以启动新的上线版本。
  • 使用 Deployment 状态来判定上线过程是否出现停滞。
  • 清理较旧的不再需要的 ReplicaSet 。

2. 创建 deployment

2.1 编写 yaml 文件

创建了一个 ReplicaSet,负责启动三个 nginx​ Pod,文件名为 nginx-deployment.yaml

apiVersion: apps/v1 # 注意这里与Pod的区别,Deployment是apps/v1而不是v1,可通过kubectl explain deployment查看 kind: Deployment # 资源类型为Deployment metadata: # deployment元数据 name: nginx-deployment # Deployment名称 labels: # deployment标签 app: nginx # 定义deployment标签为app:nginx spec: replicas: 3 # Pod的数量,Deployment会确保一直有3个Pod运行 selector: # Label Selector matchLabels: # 匹配pod标签 app: nginx # 匹配pod的标签内容为app:nginx template: # Pod的定义,用于创建Pod,也称为Pod template metadata: # pod元数据 labels: # pod标签 app: nginx # 定义pod标签内容为app:nginx spec: # 容器的定义,用于创建容器 containers: - name: nginx # 容器的名称 image: nginx:1.14.2 # 容器使用的镜像 ports: # 设置暴露端口 - containerPort: 80 # 容器端口80 resources: # 定义容器的使用资源 limits: # 限制 cpu: 200m # cpu最多使用200毫颗(0.2颗) memory: 300Mi # 内存最多使用300Mi requests: # 最少需要 cpu: 100m # cpu至少需要100毫颗(0.1颗) memory: 200Mi # 内存至少需要200Mi

说明

  • 创建名为 nginx-deployment​​(由 .metadata.name​​ 字段标明)的 Deployment。 该名称将成为后续创建 ReplicaSet 和 Pod 的命名基础。 参阅编写 Deployment 规约获取更多详细信息。

  • 该 Deployment 创建一个 ReplicaSet,它创建三个(由 .spec.replicas​​ 字段标明)Pod 副本。

  • .spec.selector​​ 字段定义所创建的 ReplicaSet 如何查找要管理的 Pod。选择在 Pod 模板中定义的标签(app: nginx​​)。 不过,更复杂的选择规则是也可能的,只要 Pod 模板本身满足所给规则即可。

    **注意:**​spec.selector.matchLabels​ 字段是 {key,value}​ 键值对映射。 在 matchLabels​ 映射中的每个 {key,value}​ 映射等效于 matchExpressions​ 中的一个元素, 即其 key​ 字段是 “key”,operator​ 为 “In”,values​ 数组仅包含 “value”。 在 matchLabels​ 和 matchExpressions​ 中给出的所有条件都必须满足才能匹配。

  • template​ 字段包含以下子字段:

    • Pod 被使用 .metadata.labels​ 字段打上 app: nginx​ 标签。
    • Pod 模板规约(即 .template.spec​ 字段)指示 Pod 运行一个 nginx​ 容器, 该容器运行版本为 1.14.2 的 nginxDocker Hub 镜像。
    • 创建一个容器并使用 .spec.template.spec.containers[0].name​ 字段将其命名为 nginx​。
    • 打开端口 80 以供 Pod 使用。

2.2 创建 deployment

kubectl apply -f nginx-deployment.yaml

2.3 查看运行状态

查看 deployment 运行状态

[root@k8s-deploy yaml]#kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 41s

在检查集群中的 Deployment 时,所显示的字段有:

  • NAME​ 列出了名字空间中 Deployment 的名称。
  • READY​ 显示应用程序的可用的“副本”数。显示的模式是“就绪个数/期望个数”。
  • UP-TO-DATE​ 显示为了达到期望状态已经更新的副本数。
  • AVAILABLE​ 显示应用可供用户使用的副本数。
  • AGE​ 显示应用程序运行的时间。

**注意:**期望副本数是根据 .spec.replicas​ 字段设置。

当前显示 Deployment 已创建全部三个副本,并且所有副本都是最新的(它们包含最新的 Pod 模板) 并且可用。

2.4 查看上线状态

查看 Deployment 上线状态

[root@k8s-deploy yaml]#kubectl describe deploy nginx-deployment Name: nginx-deployment Namespace: default CreationTimestamp: Wed, 25 Jan 2023 13:49:39 +0800 Labels: app=nginx Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx Containers: nginx: Image: nginx:1.14.2 Port: 80/TCP Host Port: 0/TCP Limits: cpu: 200m memory: 300Mi Requests: cpu: 100m memory: 200Mi Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-6559b4d948 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 96s deployment-controller Scaled up replica set nginx-deployment-6559b4d948 to 3

2.5 查看 ReplicaSet(​rs​)

查看 Deployment 创建的 ReplicaSet(rs)

[root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-6559b4d948 3 3 3 2m15s

ReplicaSet 输出中包含以下字段:

  • NAME​ 列出名字空间中 ReplicaSet 的名称;
  • DESIRED​ 显示应用的期望副本个数,即在创建 Deployment 时所定义的值。 此为期望状态;
  • CURRENT​ 显示当前运行状态中的副本个数;
  • READY​ 显示应用中有多少副本可以为用户提供服务;
  • AGE​ 显示应用已经运行的时间长度。

**注意:**ReplicaSet 的名称格式始终为 [Deployment 名称]-[哈希]​。 该名称将成为所创建的 Pod 的命名基础(pod 命名为:ReplicaSet ​ [name]​+pod [哈希]​)。 其中哈希字符串与 ReplicaSet 上的 pod-template-hash​ 标签一致。

2.6 查看 Pod 标签

查看每个 Pod 自动生成的标签

[root@k8s-deploy yaml]#kubectl get pod --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-6559b4d948-l4nsj 1/1 Running 0 3m24s app=nginx,pod-template-hash=6559b4d948 nginx-deployment-6559b4d948-p7v6l 1/1 Running 0 3m24s app=nginx,pod-template-hash=6559b4d948 nginx-deployment-6559b4d948-vq5k8 1/1 Running 0 3m24s app=nginx,pod-template-hash=6559b4d948

**注意:**必须在 Deployment 中指定适当的选择算符和 Pod 模板标签(在本例中为 app: nginx​)。 标签或者选择算符不要与其他控制器(包括其他 Deployment 和 StatefulSet)重叠。 Kubernetes 不会阻止你这样做,但是如果多个控制器具有重叠的选择算符, 它们可能会发生冲突执行难以预料的操作。

2.7 Pod-template-hash 标签

Deployment 控制器将 pod-template-hash​ 标签添加到 Deployment 所创建或收留的每个 ReplicaSet 。

此标签可确保 Deployment 的子 ReplicaSets 不重叠。 标签是通过对 ReplicaSet 的 PodTemplate​ 进行哈希处理。 所生成的哈希值被添加到 ReplicaSet 选择算符、Pod 模板标签,并存在于在 ReplicaSet 可能拥有的任何现有 Pod 中。

3. 更新 deployment

  • 仅当 Deployment Pod 模板(即 .spec.template​​​)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
  • 通过更改 Deployment 的 Pod 模板规范来更新 Deployment。更改规范字段会自动触发更新发布。可以使用 kubectl​​​、Kubernetes API。
  • 默认情况下,当 Deployment 触发更新时,Deployment 会停止 Pod,逐渐将 Pod 数量减少到零,然后排出并终止 Pod。然后,Deployment 使用经过更新的 Pod 模板来产生新的 Pod。
  • 只有正在运行的新 Pod 达到足够数量时,才会删除旧 Pod,同时只有删除的旧 Pod 达到足够数量时,才会创建新 Pod。如需查看 Pod 生成和移除的顺序,可运行 kubectl describe deployments​​​​查看。
  • Deployment 可以确保正在运行的副本数量至少比所需数量少一个,同时最多只有一个 Pod 不可用。同样,Deployment 可以确保正在运行的副本数量最多比所需数量多一个,正在运行的 Pod 数量最多比所需数量多一个。

3.1 更新

如需将 nginx Pod 镜像从 nginx:1.14.2​升级至 nginx:1.16.1​ ,更新 deployment 方式有:

  • 命令方式更新
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 # 或者kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1

或者执行 edit​ 操作并将 .spec.template.spec.containers[0].image​ 从 nginx:1.14.2​ 更改至 nginx:1.16.1​。

kubectl edit deployment/nginx-deployment

  • 修改 yaml 文件更新

将原 yaml 文件中 .spec.template.spec.containers[0].image​ 从 nginx:1.14.2​ 更改至 nginx:1.16.1​。

# 修改完成后,执行如下命令 kubectl apply -f nginx-deployment.yaml

更新过程状态如下:

# 查看上线状态 [root@k8s-deploy yaml]#kubectl rollout status deploy/nginx-deployment Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3 new replicas have been updated... # 更新过程,先创建新pod,原pod保留,待一个新pod正常运行后,删除一个旧pod [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-78fb746c6d-c8mc4 1/1 Running 0 10m nginx-deployment-79cd9bd469-27pvc 0/1 ContainerCreating 0 84s nginx-deployment-79cd9bd469-78l9g 1/1 Running 0 3m46s nginx-deployment-79cd9bd469-wspvh 1/1 Running 0 2m41s # 更新完成,保留3个新的pod,旧pod删除 [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-79cd9bd469-27pvc 1/1 Running 0 96s nginx-deployment-79cd9bd469-78l9g 1/1 Running 0 3m58s nginx-deployment-79cd9bd469-wspvh 1/1 Running 0 2m53s

3.2 查看状态

# 查看deployment [root@k8s-deploy yaml]#kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 12m # 查看rs [root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-78fb746c6d 0 0 0 12m nginx-deployment-79cd9bd469 3 3 3 4m33s # 查看pod [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-79cd9bd469-27pvc 1/1 Running 0 96s nginx-deployment-79cd9bd469-78l9g 1/1 Running 0 3m58s nginx-deployment-79cd9bd469-wspvh 1/1 Running 0 2m53s

4. 回滚 deployment

当 Deployment 不稳定时(例如进入反复崩溃状态),需要回滚 Deployment;默认情况下,系统保留 10 次 Deployment 的 revision,以便可以随时回滚 (可以修改 revision history limit​ 来更改保存的历史记录数)。

**说明:**Deployment 被触发上线时,系统就会创建 Deployment 的新的 revision。这意味着仅当 Deployment 的 Pod 模板(.spec.template​)发生更改时,才会创建新 revision:例如,模板的标签或容器镜像发生变化。其他更新,如 Deployment 的扩缩容操作不会创建 Deployment revision。 这是为了方便同时执行手动缩放或自动缩放。这意味着当回退到历史 revision 时,只有 Deployment 中的 Pod 模板部分才会回退。

查看 Deployment 历史版本

假设在更新 Deployment 时犯了一个拼写错误,将镜像名称命名设置为 nginx:1.161​ 而不是 nginx:1.16.1​:

kubectl set image deployment/nginx-deployment nginx=nginx:1.161
  1. 检查 Deployment 修订历史
[root@k8s-deploy yaml]#kubectl rollout history deployment/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 <none> 2 <none> 4 <none> 5 <none> 6 <none>
  1. 要查看指定历史版本的详细信息
[root@k8s-deploy yaml]#kubectl rollout history deployment/nginx-deployment --revision=5 deployment.apps/nginx-deployment with revision #5 Pod Template: Labels: app=nginx pod-template-hash=79cd9bd469 Containers: nginx: Image: nginx:1.16.1 Port: 80/TCP Host Port: 0/TCP Limits: cpu: 200m memory: 300Mi Requests: cpu: 100m memory: 200Mi Environment: <none> Mounts: <none> Volumes: <none>

回滚到之前的版本

  1. 回滚到历史版本
  • 回滚到上一个版本
kubectl rollout undo deployment/nginx-deployment
  • 回滚到指定版本

使用 --to-revision​ 回滚到指定版本(如版本 5)

kubectl rollout undo deployment/nginx-deployment --to-revision=5

  1. 检查回滚是否成功以及 Deployment 是否正在运行
[root@k8s-deploy yaml]#kubectl get deployment nginx-deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 7h56m
  1. 查看 Deployment 描述信息:
[root@k8s-deploy yaml]#kubectl describe deployment nginx-deployment ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 51m deployment-controller Scaled up replica set nginx-deployment-59c554777d to 1 Normal ScalingReplicaSet 48m deployment-controller Scaled down replica set nginx-deployment-59c554777d to 0 Normal ScalingReplicaSet 16m deployment-controller Scaled up replica set nginx-deployment-f75dc4657 to 1 Normal ScalingReplicaSet 9m35s deployment-controller Scaled down replica set nginx-deployment-f75dc4657 to 0

5. 缩放 deployment

执行缩放命令

# 将nginx-deployment副本扩展至6个 kubectl scale deployment/nginx-deployment --replicas=6

验证

# 查看deploy [root@k8s-deploy yaml]#kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 6/6 6 6 8h # 查看rs [root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-59c554777d 0 0 0 60m nginx-deployment-6559b4d948 0 0 0 8h nginx-deployment-78fb746c6d 0 0 0 83m nginx-deployment-79cd9bd469 6 6 6 75m nginx-deployment-f75dc4657 0 0 0 26m # 查看pod [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-79cd9bd469-27pvc 1/1 Running 0 73m nginx-deployment-79cd9bd469-56dsx 1/1 Running 0 6m30s nginx-deployment-79cd9bd469-78l9g 1/1 Running 0 75m nginx-deployment-79cd9bd469-jhbs4 1/1 Running 0 6m30s nginx-deployment-79cd9bd469-qmz68 1/1 Running 0 6m30s nginx-deployment-79cd9bd469-wspvh 1/1 Running 0 74m

6. 暂停和恢复 deployment

在触发一次或多次更新前暂停一个 Deployment,然后再恢复它。这样就能在 Deployment 暂停期间进行多次修复工作,而不会发出不必要的 rollout。

以 nginx-deployment 为例:

  1. 获取 deployment 信息
[root@k8s-deploy yaml]#kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 6/6 6 6 8h [root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-59c554777d 0 0 0 72m nginx-deployment-6559b4d948 0 0 0 8h nginx-deployment-78fb746c6d 0 0 0 95m nginx-deployment-79cd9bd469 6 6 6 87m nginx-deployment-f75dc4657 0 0 0 38m
  1. 暂停 deployment 上线
kubectl rollout pause deploy/nginx-deployment
  1. 查看历史更新记录
[root@k8s-deploy yaml]#kubectl rollout history deploy/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 <none> 4 <none> 6 <none> 7 <none> 8 <none>
  1. 更新 deployment 镜像
kubectl set image deploy/nginx-deployment nginx=nginx:1.16.0
  1. 查看历史更新记录

没有新的上线被触发

[root@k8s-deploy yaml]#kubectl rollout history deploy/nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 1 <none> 4 <none> 6 <none> 7 <none> 8 <none>
  1. 获取上线状态验证现有的 ReplicaSet 没有被更改
[root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-59c554777d 0 0 0 82m nginx-deployment-6559b4d948 0 0 0 8h nginx-deployment-78fb746c6d 0 0 0 105m nginx-deployment-79cd9bd469 6 6 6 97m nginx-deployment-f75dc4657 0 0 0 48m

暂停 Deployment 上线之前的初始状态将继续发挥作用,根据需要可执行很多更新操作,但新的更新在 Deployment 上线被暂停期间不会产生任何效果。

  1. 恢复 deployment 上线
kubectl rollout resume deploy/nginx-deployment
  1. 查看上线过程
[root@k8s-deploy yaml]#kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 5/6 3 5 8h [root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-59c554777d 0 0 0 87m nginx-deployment-6559b4d948 0 0 0 8h nginx-deployment-78fb746c6d 0 0 0 109m nginx-deployment-79cd9bd469 5 5 5 102m nginx-deployment-9dd69d6c8 3 3 0 89s nginx-deployment-f75dc4657 0 0 0 52m [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-79cd9bd469-27pvc 1/1 Running 0 100m nginx-deployment-79cd9bd469-56dsx 1/1 Running 0 32m nginx-deployment-79cd9bd469-78l9g 1/1 Running 0 102m nginx-deployment-79cd9bd469-jhbs4 1/1 Running 0 32m nginx-deployment-79cd9bd469-wspvh 1/1 Running 0 101m nginx-deployment-9dd69d6c8-cm9nl 0/1 ContainerCreating 0 100s nginx-deployment-9dd69d6c8-vlw8d 0/1 ContainerCreating 0 100s nginx-deployment-9dd69d6c8-vp9t8 0/1 ContainerCreating 0 100s
  1. 查看完成状态
[root@k8s-deploy yaml]#kubectl get rs NAME DESIRED CURRENT READY AGE nginx-deployment-59c554777d 0 0 0 92m nginx-deployment-6559b4d948 0 0 0 8h nginx-deployment-78fb746c6d 0 0 0 114m nginx-deployment-79cd9bd469 0 0 0 107m nginx-deployment-9dd69d6c8 6 6 6 6m25s nginx-deployment-f75dc4657 0 0 0 57m [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-9dd69d6c8-2dfwz 1/1 Running 0 4m21s nginx-deployment-9dd69d6c8-4tvr5 1/1 Running 0 4m20s nginx-deployment-9dd69d6c8-77hff 1/1 Running 0 4m24s nginx-deployment-9dd69d6c8-cm9nl 1/1 Running 0 6m54s nginx-deployment-9dd69d6c8-vlw8d 1/1 Running 0 6m54s nginx-deployment-9dd69d6c8-vp9t8 1/1 Running 0 6m54s

**注意:**不可以回滚处于暂停状态的 Deployment,除非先恢复其执行状态。

7. deployment 状态

Deployment 在其生命周期中可以处于以下三种状态:Progressing(进行中),Complete(已完成),Failed(失败)。

Progressing

执行下面的任务期间,Kubernetes 标记 Deployment 为 Progressing:

  • Deployment 创建新的 ReplicaSet
  • Deployment 正在为其最新的 ReplicaSet 扩容
  • Deployment 正在为其旧有的 ReplicaSet(s) 缩容
  • 新的 Pod 已经就绪或者可用(就绪至少持续了 MinReadySeconds 秒)。

当上线过程进入“Progressing”状态时,Deployment 控制器会向 Deployment 的 .status.conditions​ 中添加包含下面属性的状况条目:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetCreated​ | reason: FoundNewReplicaSet​ | reason: ReplicaSetUpdated

可执行 kubectl rollout status​ 监视 Deployment 的进度。

Complete

当 Deployment 具有以下特征时,Kubernetes 将其标记为 Complete

  • 与 Deployment 关联的所有副本都已更新到指定的最新版本,这意味着之前请求的所有更新都已完成。
  • 与 Deployment 关联的所有副本都可用。
  • 未运行 Deployment 的旧副本。

当上线过程进入“Complete”状态时,Deployment 控制器会向 Deployment 的 .status.conditions​ 中添加包含下面属性的状况条目:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetAvailable

Progressing​ 状态值会持续为 "True"​,直至新的上线动作被触发。 即使副本的可用状态发生变化(进而影响 Available​ 状况),Progressing​ 状况的值也不会变化。

可以使用 kubectl rollout status​ 检查 Deployment 是否已完成。 如果上线成功完成,kubectl rollout status​ 输出 successfully rolled out​。

Failed

Deployment 可能会在尝试部署其最新的 ReplicaSet 受挫,一直处于未完成状态。 造成此情况一些可能因素如下:

  • 配额(Quota)不足
  • 就绪探测(Readiness Probe)失败
  • 镜像拉取错误
  • 权限不足
  • 限制范围(Limit Ranges)问题
  • 应用程序运行时的配置错误

超过截止时间后,Deployment 控制器将添加具有以下属性的 Deployment 状况到 Deployment 的 .status.conditions​ 中:

  • type: Progressing
  • status: "False"
  • reason: ProgressDeadlineExceeded

这一状况也可能会比较早地失败,因而其状态值被设置为 "False"​, 其原因为 ReplicaSetCreateError​。 一旦 Deployment 上线完成,就不再考虑其期限。

对失败 Deployment 的操作​** **

可应用于已完成的 Deployment 的所有操作也适用于失败的 Deployment。 可以对其执行扩缩容、回滚到以前的修订版本等操作,或者在需要对 Deployment 的 Pod 模板应用多项调整时,将 Deployment 暂停。

8. 清理策略

可以在 Deployment 中设置 .spec.revisionHistoryLimit​ 字段以指定保留此 Deployment 的多少个旧有 ReplicaSet。其余的 ReplicaSet 将在后台被垃圾回收。 默认情况下此值为 10。

**注意:**将此字段设置为 0 将导致 Deployment 的所有历史记录被清空,因此 Deployment 将无法回滚。

9. 金丝雀部署

如果要使用 Deployment 向用户子集或服务器子集上线版本, 则可以遵循资源管理所描述的金丝雀模式, 创建多个 Deployment,每个版本一个。

金丝雀发布常见的做法是部署一个新应用版本(在 Pod 模板中通过镜像标签指定),保持新旧版本应用同时运行。 这样,新版本在完全发布之前也可以接收实时的生产流量。

10. 编写 Deployment 规范

https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/workload-resources/deployment-v1/

在所有的 Kubernetes 配置中,Deployment 也需要 apiVersion​​,kind​​ 和 metadata​​ 这些配置项。有关配置文件的其他信息,请参考部署 Deployment、 配置容器和使用 kubectl 管理资源等相关文档。

Pod Template

.spec​ 中只有 .spec.template​ 和 .spec.selector​ 是必需的字段。

.spec.template​ 是 pod 的一个模板。它和 pod 的语法规则完全相同,只是这里它是嵌套的,因此不需要 apiVersion​ 或 kind​。

除了 Pod 的必填字段外,Deployment 中的 Pod 模板必须指定适当的标签和适当的重新启动策略。 对于标签,请确保不要与其他控制器重叠。请参考 selector​。

只有 .spec.template.spec.restartPolicy​ 等于 Always​ 才是被允许的,这也是在没有指定时的默认设置。

Replicas

.spec.replicas​ 是可以选字段,指定期望的 pod 数量,默认是 1。

若一个 HorizontalPodAutoscaler(或者其他执行水平扩缩操作的类似 API)在管理 Deployment 的扩缩, 则不要设置 .spec.replicas​。

Selector

.spec.selector​ 是指定本 Deployment 的 Pod 标签选择算符的必需字段。

.spec.selector​ 必须匹配 .spec.template.metadata.labels​,否则请求会被 API 拒绝。

在 API apps/v1​版本中,.spec.selector​ 和 .metadata.labels​ 如果没有设置的话, 不会被默认设置为 .spec.template.metadata.labels​,所以需要明确进行设置。 同时在 apps/v1​版本中,Deployment 创建后 .spec.selector​ 是不可变的。

当 Pod 的标签和选择算符匹配,但其模板和 .spec.template​ 不同时,或者此类 Pod 的总数超过 .spec.replicas​ 的设置时,Deployment 会终结之。 如果 Pod 总数未达到期望值,Deployment 会基于 .spec.template​ 创建新的 Pod。

如果有多个控制器的选择算符发生重叠,则控制器之间会因冲突而无法正常工作。

注意:不应直接创建与此选择算符匹配的 Pod,也不应通过创建另一个 Deployment 或者类似于 ReplicaSet 或 ReplicationController 这类控制器来创建标签与此选择算符匹配的 Pod。 如果这样做,第一个 Deployment 会认为它创建了这些 Pod。 Kubernetes 不会阻止你这么做。

strategy

.spec.strategy​ 策略指定用于用新 Pod 替换旧 Pod 的策略。 .spec.strategy.type​ 可以是 “Recreate” 或 “RollingUpdate”。“RollingUpdate” 是默认值。

  • Recreate

如果 .spec.strategy.type==Recreate​,在创建新 Pod 之前,所有现有的 Pod 会被杀死。

**说明:**这只会确保为了升级而创建新 Pod 之前其他 Pod 都已终止。如果升级一个 Deployment, 所有旧版本的 Pod 都会立即被终止。控制器等待这些 Pod 被成功移除之后, 才会创建新版本的 Pod。如果手动删除一个 Pod,其生命周期是由 ReplicaSet 来控制的, 后者会立即创建一个替换 Pod(即使旧的 Pod 仍然处于 Terminating 状态)。 如果需要一种“最多 n 个”的 Pod 个数保证,你需要考虑使用 StatefulSet。

  • RollingUpdate

Deployment 会在 .spec.strategy.type==RollingUpdate​时,采取滚动更新的方式更新 Pod。可以指定 maxUnavailable​ 和 maxSurge​ 来控制滚动更新过程。

Max Unavailable(最大不可用)

.spec.strategy.rollingUpdate.maxUnavailable​ 是一个可选字段,用来指定 更新过程中不可用的 Pod 的个数上限。该值可以是绝对数字(例如,5),也可以是所需 Pod 的百分比(例如,10%)。百分比值会转换成绝对数并去除小数部分。 如果 .spec.strategy.rollingUpdate.maxSurge​ 为 0,则此值不能为 0。 默认值为 25%。

例如,当此值设置为 30% 时,滚动更新开始时会立即将旧 ReplicaSet 缩容到期望 Pod 个数的 70%。 新 Pod 准备就绪后,可以继续缩容旧有的 ReplicaSet,然后对新的 ReplicaSet 扩容, 确保在更新期间可用的 Pod 总数在任何时候都至少为所需的 Pod 个数的 70%

Max Surge(最大峰值)

.spec.strategy.rollingUpdate.maxSurge​ 是一个可选字段,用来指定可以创建的超出期望 Pod 个数的 Pod 数量。此值可以是绝对数(例如,5)或所需 Pod 的百分比(例如,10%)。 如果 MaxUnavailable​ 为 0,则此值不能为 0。百分比值会通过向上取整转换为绝对数。 此字段的默认值为 25%。

例如,当此值为 30% 时,启动滚动更新后,会立即对新的 ReplicaSet 扩容,同时保证新旧 Pod 的总数不超过所需 Pod 总数的 130%。一旦旧 Pod 被杀死,新的 ReplicaSet 可以进一步扩容, 同时确保更新期间的任何时候运行中的 Pod 总数最多为所需 Pod 总数的 130%。

ProgressDeadlineSeconds

.spec.progressDeadlineSeconds​(进度期限秒数) 是一个可选字段,用于指定系统在报告 Deployment failed 状态之前等待 Deployment 取得进展的秒数。 这类报告会在资源状态中体现为 type: Progressing​、status: False​、 reason: ProgressDeadlineExceeded​。Deployment 控制器将在默认 600 毫秒内持续重试 Deployment。 将来,一旦实现了自动回滚,Deployment 控制器将在探测到这样的条件时立即回滚 Deployment。

如果指定,则此字段值需要大于 .spec.minReadySeconds​ 取值。

MinReadySeconds

.spec.minReadySeconds​ (最短就绪时间)是一个可选字段,用于指定新创建的 Pod 在没有任意容器崩溃情况下的最小就绪时间, 只有超出这个时间 Pod 才被视为可用。默认值为 0(Pod 在准备就绪后立即将被视为可用)。 要了解何时 Pod 被视为就绪, 可参考容器探针。

RevisionHistoryLimit

Deployment 的修订历史记录存储在它所控制的 ReplicaSets 中。

.spec.revisionHistoryLimit​ 是一个可选字段,用来设定出于回滚目的所要保留的旧 ReplicaSet 数量。 这些旧 ReplicaSet 会消耗 etcd 中的资源,并占用 kubectl get rs​ 的输出。 每个 Deployment 修订版本的配置都存储在其 ReplicaSets 中;因此,一旦删除了旧的 ReplicaSet, 将失去回滚到 Deployment 的对应修订版本的能力。 默认情况下,系统保留 10 个旧 ReplicaSet,但其理想值取决于新 Deployment 的频率和稳定性。

更具体地说,将此字段设置为 0 意味着将清理所有具有 0 个副本的旧 ReplicaSet。 在这种情况下,无法撤消新的 Deployment 上线,因为它的修订历史被清除了。

Paused

.spec.paused​​ 是用于暂停和恢复 Deployment 的可选布尔字段。 暂停的 Deployment 和未暂停的 Deployment 的唯一区别是,Deployment 处于暂停状态时, PodTemplateSpec 的任何修改都不会触发新的上线。 Deployment 在创建时是默认不会处于暂停状态。

service

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/service-resources/service-v1/

将运行在一组 Pod 上的应用程序公开为网络服务的抽象方法。使用 Kubernetes 无需修改应用程序去使用不熟悉的服务发现机制。 Kubernetes 为 Pod 提供自己的 IP 地址,并为一组 Pod 提供相同的 DNS 名, 并且可以在它们之间进行负载均衡。

Kubernetes Service 是为了管理具有相同功能的一组 Pod 而定义的一种对象,Service 具体的作用和场景如下:

  • 通过 Pod 的 Label Selector 动态匹配后端 endpoint;
  • 将服务和应用解耦合,简化外系统调用 K8S 服务的复杂度,屏蔽 K8S 内部的实现细节;
  • Service 通过 kube-proxy 借助 iptables/ipvs 提供负载均衡的能力,实现反向代理,将请求转发到合适的 Pod 上。

service 工作流程

image

定义 service

https://kubernetes.io/zh-cn/docs/reference/kubernetes-api/service-resources/service-v1/

Service 是软件服务(例如 nginx)的命名抽象,包含代理要侦听的本地端口(例如 80)和一个选择算符, 选择算符用来确定哪些 Pod 将响应通过代理发送的请求。

  • apiVersion​: v1
  • kind​: Service
  • metadata (ObjectMeta)
    标准的对象元数据。
  • spec (ServiceSpec)
    spec 定义 Service 的行为。
  • status(ServiceStatus)
    最近观察到的 Service 状态。由系统填充。只读。

准备环境

需先创建 pod,示例,创建一个 3 副本的 Deployment,即 3 个 Pod,且 Pod 上带有标签“app: nginx”:

apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.16.1 ports: - containerPort: 80

服务类型

对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部的 IP 地址。Kubernetes ServiceTypes​ 允许指定你所需要的 Service 类型。

Type​ 的取值以及行为如下:

  • ClusterIP​:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是你没有为服务显式指定 type​ 时使用的默认值。
  • NodePort​:通过每个节点上的 IP 和静态端口(NodePort​)暴露服务。 为了让节点端口可用,Kubernetes 设置了集群 IP 地址,这等同于你请求 type: ClusterIP​ 的服务。
  • LoadBalancer​:使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort​ 服务和 ClusterIP​ 服务上。
  • ExternalName​:通过返回 CNAME​ 记录和对应值,可以将服务映射到 externalName​ 字段的内容(例如,foo.bar.example.com​)。无需创建任何类型代理。

**说明:**kube-dns 1.7 及以上版本或者 CoreDNS 0.0.8 及以上版本才能使用 ExternalName​ 类型。

type​ 字段被设计为嵌套功能 - 每个级别都添加到前一个级别。

还可以使用 Ingress 来暴露自己的服务,Ingress 不是一种服务类型,但它充当集群的入口点。 它可以将路由规则整合到一个资源中,因为它可以在同一 IP 地址下公开多个服务。

image

其中绿色的代表从外向内的访问模式;蓝色的代表从内向外的访问模式,黄色代表集群内部的访问模式。可以看到,除了 ExternalName 类型之外,其余三种类型都是逐层封装而来的。

ClusterIP

这是 K8S 默认的服务类型,只能在 K8S 中进行服务通信。在 ClientIP 中,K8S 会在 Service 创建完毕后提供一个内部 IP 作为 ClientIP 属性,K8S 内部服务可以通过 ClientIP 或者 ServiceName 来访问该服务。

创建 service

以 yaml 方式创建

apiVersion: v1 kind: Service metadata: name: clusterip-nginx-service # Service的名称 spec: selector: # Label Selector,选择包含app=nginx标签的Pod app: nginx type: ClusterIP # type可不配,不配的话默认就是ClusterIP类型 # clusterIP: 10.100.13.127 # 可不配,不配的话系统会分配一个随机的IP并保持不变 ports: - targetPort: 80 # Pod的端口 port: 8080 # Service对外暴露的端口 protocol: TCP # 协议类型,TCP、UDP和SCTP,默认类型为TCP

执行命令

kubectl apply -f clusterip-nginx-service.yaml

查看状态
# 查看service类型、端口,选择pod的标签 [root@k8s-deploy yaml]#kubectl get svc -owide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR clusterip-nginx-service ClusterIP 10.100.180.205 <none> 8080/TCP 45s app=nginx kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 8d <none> # 查看pod标签、IP [root@k8s-deploy yaml]#kubectl get pod --show-labels -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS nginx-deployment-66b957f9d-7jhkn 1/1 Running 0 35m 10.200.169.152 10.0.0.42 <none> <none> app=nginx,pod-template-hash=66b957f9d nginx-deployment-66b957f9d-k69d5 1/1 Running 0 35m 10.200.107.212 10.0.0.43 <none> <none> app=nginx,pod-template-hash=66b957f9d nginx-deployment-66b957f9d-s7fdq 1/1 Running 0 35m 10.200.135.202 10.0.0.13 <none> <none> app=nginx,pod-template-hash=66b957f9d # 查看service对应后端pod的IP:端口 [root@k8s-deploy yaml]#kubectl get ep NAME ENDPOINTS AGE clusterip-nginx-service 10.200.107.212:80,10.200.135.202:80,10.200.169.152:80 69s kubernetes 10.0.0.11:6443,10.0.0.12:6443,10.0.0.13:6443 8d

创建一个名称为 "clusterip-nginx-service" 的 Service 对象,它会将请求代理到使用 TCP 端口 8080,并且具有标签 app=nginx​ 的 Pod 上。

Kubernetes 为该服务分配一个 IP 地址(有时称为“集群 IP”),该 IP 地址由服务代理使用。

服务选择算符的控制器不断扫描与其选择算符匹配的 Pod,然后将所有更新发布到称为“clusterip-nginx-service”的 Endpoint 对象。

**说明:**Service 能够将一个接收 port​​​ 映射到任意的 targetPort​​​。 默认情况下,targetPort​​​ 将被设置为与 port​​​ 字段相同的值。

验证测试

**注意:**需要在 k8s 集群内部测试

[root@k8s-master1 ~]#curl 10.100.180.205:8080 <!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>

NodePort

NodePort 类型的 Service 可以让 Kubernetes 集群每个节点上保留一个相同的端口, 外部访问连接首先访问节点 IP:Port(端口默认值:30000-32767),然后将这些连接转发给服务对应的 Pod。

image

创建 service

以 yaml 方式

apiVersion: v1 kind: Service metadata: name: nodeport-nginx-service spec: type: NodePort selector: app: nginx ports: # 默认情况下,为了方便起见,targetPort 被设置为与port字段相同的值。 - port: 80 targetPort: 80 # 可选字段 # 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767) nodePort: 30120

执行

kubectl apply -f nodeport-nginx-service.yaml
查看状态
# 查看service类型、映射端口 [root@k8s-deploy yaml]#kubectl get svc -owide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 8d <none> nodeport-nginx-service NodePort 10.100.40.40 <none> 80:30120/TCP 6s app=nginx # 查看pod标签、IP [root@k8s-deploy yaml]#kubectl get pod --show-labels -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS nginx-deployment-66b957f9d-7jhkn 1/1 Running 0 3m48s 10.200.169.152 10.0.0.42 <none> <none> app=nginx,pod-template-hash=66b957f9d nginx-deployment-66b957f9d-k69d5 1/1 Running 0 3m48s 10.200.107.212 10.0.0.43 <none> <none> app=nginx,pod-template-hash=66b957f9d nginx-deployment-66b957f9d-s7fdq 1/1 Running 0 3m48s 10.200.135.202 10.0.0.13 <none> <none> app=nginx,pod-template-hash=66b957f9d # 查看service对应后端pod的IP:端口 [root@k8s-deploy yaml]#kubectl get ep NAME ENDPOINTS AGE kubernetes 10.0.0.11:6443,10.0.0.12:6443,10.0.0.13:6443 8d nodeport-nginx-service 10.200.107.212:80,10.200.135.202:80,10.200.169.152:80 42s

创建一个名称为 "nodeport-nginx-service" 的 Service 对象,它会将 TCP 10.100.40.40:80(集群内部访问)/宿主机 ip:30120(外部访问)请求代理到后端标签 app=nginx​ 的 Pod 上。

验证测试
  • 集群内部访问 10.100.225.73:80
[root@k8s-master1 ~]#curl 10.100.225.73:80 <!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>

  • 浏览器访问集群任意一宿主机 ip:30120

image

LoadBalancer

LoadBalancer 类型的 service 是可以实现集群外部访问服务的另外一种解决方案。不过并不是所有的 k8s 集群都会支持,大多是在公有云托管集群中会支持该类型。负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer​字段被发布出去。

示例:

apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app.kubernetes.io/name: MyApp ports: - protocol: TCP port: 80 targetPort: 9376 clusterIP: 10.0.171.239 type: LoadBalancer status: loadBalancer: ingress: - ip: 192.0.2.127

来自外部负载均衡器的流量将直接重定向到后端 Pod 上,不过实际它们是如何工作的,这要依赖于云提供商。

ExternalName

ExternalName 类型的 service 方式。该类型的好处是内部服务访问外部服务的时候是通过别名来访问的,屏蔽了外部服务的真实信息,外部服务对内部服务透明,外部服务的修改基本上不会影响到内部服务的访问,做到了内部服务和外部服务解耦合。

示例,以下 Service 定义将 prod​ 名称空间中的 my-service​ 服务映射到 my.database.example.com​:

apiVersion: v1 kind: Service metadata: name: my-service namespace: prod spec: type: ExternalName externalName: my.database.example.com

**说明:**ExternalName 服务接受 IPv4 地址字符串,但作为包含数字的 DNS 名称,而不是 IP 地址。 类似于 IPv4 地址的外部名称不能由 CoreDNS 或 ingress-nginx 解析,因为外部名称旨在指定规范的 DNS 名称。 要对 IP 地址进行硬编码,请考虑使用无头 Services。

说明

定义端口名称

Pod 中的端口定义是有名字的,你可以在 Service 的 targetPort​​​ 属性中引用这些名称。 例如,可以通过以下方式将 Service 的 targetPort​​​ 绑定到 Pod 端口:

apiVersion: v1 kind: Pod metadata: name: nginx labels: app.kubernetes.io/name: proxy spec: containers: - name: nginx image: nginx:stable ports: - containerPort: 80 name: http-web-svc --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app.kubernetes.io/name: proxy ports: - name: name-of-service-port protocol: TCP port: 80 targetPort: http-web-svc #可配置对应pod中containerPort(80),也可配置对应的name(http-web-svc)
多端口 service

对于某些服务,你需要公开多个端口。 Kubernetes 允许你在 Service 对象上配置多个端口定义。 为服务使用多个端口时,必须提供所有端口名称,以使它们无歧义。

示例:

apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app.kubernetes.io/name: MyApp ports: - name: http protocol: TCP port: 80 targetPort: 9376 - name: https protocol: TCP port: 443 targetPort: 9377

与一般的 Kubernetes 名称一样,端口名称只能包含小写字母数字字符和 -​​。 端口名称还必须以字母数字字符开头和结尾。

例如,名称 123-abc​​​​​ 和 web​​​​​ 有效,但是 123_abc​​​​​ 和 -web​​​​​ 无效。

无选择算符的 service

由于选择算符的存在,服务最常见的用法是为 Kubernetes Pod 的访问提供抽象, 但是当与相应的 EndpointSlices 对象一起使用且没有选择算符时, 服务也可以为其他类型的后端提供抽象,包括在集群外运行的后端。

在以下这些场景中,都能够定义没有选择算符的 Service:

  • 希望在生产环境中使用外部的数据库集群,但测试环境使用自己的数据库。
  • 希望服务指向另一个 Namespace 中或其它集群中的服务。
  • 正在将工作负载迁移到 Kubernetes。在评估该方法时,仅在 Kubernetes 中运行一部分后端。
apiVersion: v1 kind: Service metadata: name: my-service spec: ports: - protocol: TCP port: 80 targetPort: 9376

由于此服务没有选择算符,因此不会自动创建相应的 EndpointSlice(和旧版 Endpoint)对象。 可以通过手动添加 EndpointSlice 对象,将服务映射到运行该服务的网络地址和端口:

apiVersion: discovery.k8s.io/v1 kind: EndpointSlice metadata: name: my-service-1 # 按惯例将服务的名称用作 EndpointSlice 名称的前缀 labels: # 应设置 "kubernetes.io/service-name"标签。 # 设置其值以匹配服务的名称 kubernetes.io/service-name: my-service addressType: IPv4 ports: - name: '' # 留空,因为 port 9376 未被 IANA 分配为已注册端口 appProtocol: http protocol: TCP port: 9376 endpoints: - addresses: - "10.4.5.6" # 此列表中的 IP 地址可以按任何顺序显示 - "10.1.2.3"

Headless Services

有时不需要或不想要负载均衡,以及单独的 Service IP。 遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP​​)的值为 "None"​​ 来创建 Headless​​ Service。

可以使用一个无头 Service 与其他服务发现机制进行接口,而不必与 Kubernetes 的实现捆绑在一起。

对于无头 Services​​ 并不会分配 Cluster IP,kube-proxy 不会处理它们, 而且平台也不会为它们进行负载均衡和路由。 DNS 如何实现自动配置,依赖于 Service 是否定义了选择算符。

带选择算符的服务

对定义了选择算符的无头服务,Kubernetes 控制平面在 Kubernetes API 中创建 EndpointSlice 对象, 并且修改 DNS 配置返回 A 或 AAA 条记录(IPv4 或 IPv6 地址),通过这个地址直接到达 Service​​ 的后端 Pod 上。

无选择算符的服务

对没有定义选择算符的无头服务,控制平面不会创建 EndpointSlice 对象。 然而 DNS 系统会查找和配置以下之一:

  • 对于 type: ExternalName​​ 服务,查找和配置其 CNAME 记录

  • 对所有其他类型的服务,针对 Service 的就绪端点的所有 IP 地址,查找和配置 DNS A / AAAA 条记录

    • 对于 IPv4 端点,DNS 系统创建 A 条记录。
    • 对于 IPv6 端点,DNS 系统创建 AAAA 条记录。

configmap

https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/

ConfigMap 是一种用于存储应用所需配置信息的资源类型,用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。

通过 ConfigMap 可以方便的做到配置解耦,使得不同环境有不同的配置。

configmap 应用场景:

  • 通过 Configmap 给 pod 定义全局环境变量
  • 通过 Configmap 给 pod 传递命令行参数,如 mysql -u -p 中的账户名密码可以通过 configmap 传递
  • 通过 Configmap 给 pod 中的容器服务提供配置文件,配置文件以挂载到容器的形式使用

注意:

  • Configmap 需要在使用 pod 之前创建
  • pod 只能使用位于同一个 namespace 的 Configmap,及 Configmap 不能跨 namespace 使用
  • ConfigMap 并不提供保密或者加密功能。 如果想存储的数据是机密的,请使用 Secret, 或者使用其他第三方工具来保证数据的私密性。
  • ConfigMap 中保存的数据不可超过 1M

创建 configmap

apiVersion: v1 kind: ConfigMap metadata: name: configmap-test data: # 类属性键;每一个键都映射到一个简单的值 property_1: Hello property_2: World

查看

# 创建 [root@k8s-deploy yaml]#kubectl apply -f configmap.yaml configmap/configmap-test created # 查看configmap [root@k8s-deploy yaml]#kubectl get cm NAME DATA AGE configmap-test 2 15s kube-root-ca.crt 1 8d [root@k8s-deploy yaml]#kubectl describe cm configmap-test Name: configmap-test Namespace: default Labels: <none> Annotations: <none> Data ==== property_1: ---- Hello property_2: ---- World BinaryData ==== Events: <none>

可以用以下四种方式来使用 ConfigMap 配置 Pod 中的容器:

  1. 在容器命令和参数内
  2. 容器的环境变量
  3. 在只读卷里面添加一个文件,让应用来读取
  4. 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap

在环境变量中引用 ConfigMap

ConfigMap 最为常见的使用方式就是在环境变量和 Volume 中引用。

例如下面例子中,引用了 configmap-test 的 property_1,将其作为环境变量 EXAMPLE_PROPERTY_1 的值,这样容器启动后里面 EXAMPLE_PROPERTY_1 的值就是 property_1 的值,即**“Hello”**。

apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx:1.16.1 name: container-0 resources: limits: cpu: 100m memory: 200Mi requests: cpu: 100m memory: 200Mi env: # 定义环境变量 - name: EXAMPLE_PROPERTY_1 # 请注意这里和 ConfigMap 中的键名是不一样的 valueFrom: configMapKeyRef: # 引用ConfigMap name: configmap-test # 这个值来自 ConfigMap key: property_1 # 需要取值的键 imagePullSecrets: - name: default-secret

验证

# 获取创建nginx的pod [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 38s nginx-deployment-66b957f9d-7jhkn 1/1 Running 0 145m nginx-deployment-66b957f9d-k69d5 1/1 Running 0 145m nginx-deployment-66b957f9d-s7fdq 1/1 Running 0 145m # 进入容器,查看EXAMPLE_PROPERTY_1值 [root@k8s-deploy yaml]#kubectl exec -it nginx sh kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. # echo $EXAMPLE_PROPERTY_1 Hello #

在 Volume 中引用 ConfigMap

在 Volume 中引用 ConfigMap,就是通过文件的方式直接将 ConfigMap 的每条数据填入 Volume,每条数据是一个文件,键就是文件名,键值就是文件内容。

如下示例中,创建一个名为 vol-configmap 的 Volume,这个 Volume 引用名为“configmap-test”的 ConfigMap,再将 Volume 挂载到容器的“/tmp”路径下。Pod 创建成功后,在容器的“/tmp”路径下,就有两个文件 p1 和 p2,它们的值分别为“Hello”和“World”。

apiVersion: v1 kind: Pod metadata: name: nginx-volume spec: containers: - image: nginx:1.16.1 name: container-0 resources: limits: cpu: 100m memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: vol-configmap # 挂载名为vol-configmap的Volume mountPath: "/tmp" imagePullSecrets: - name: default-secret volumes: # 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中 - name: vol-configmap configMap: # 引用ConfigMap # 提供想要挂载的 ConfigMap 的名字 name: configmap-test # 来自 ConfigMap 的一组键,将被创建为文件,如果不配置items,则 ConfigMap 中的每个键都会变成一个与该键同名的文件。path为挂载点名称,key为文件内容 items: - key: property_1 path: p1 - key: property_2 path: p2

验证

[root@k8s-deploy yaml]#kubectl apply -f volume-configmap.yaml pod/nginx-volume created [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE nginx-deployment-66b957f9d-7jhkn 1/1 Running 0 3h5m nginx-deployment-66b957f9d-k69d5 1/1 Running 0 3h5m nginx-deployment-66b957f9d-s7fdq 1/1 Running 0 3h5m nginx-volume 1/1 Running 0 14s [root@k8s-deploy yaml]#kubectl exec -it nginx-volume bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@nginx-volume:/# more /tmp/p1 Hello root@nginx-volume:/# more /tmp/p2 World root@nginx-volume:/#

被挂载的 ConfigMap 内容会自动更新

当卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。 不过,kubelet 使用的是其本地的高速缓存来获得 ConfigMap 的当前值。 高速缓存的类型可以通过 KubeletConfiguration 结构. 的 ConfigMapAndSecretChangeDetectionStrategy​ 字段来配置。

ConfigMap 既可以通过 watch 操作实现内容传播(默认形式),也可实现基于 TTL 的缓存,还可以直接经过所有请求重定向到 API 服务器。 因此,从 ConfigMap 被更新的那一刻算起,到新的主键被投射到 Pod 中去, 这一时间跨度可能与 kubelet 的同步周期加上高速缓存的传播延迟相等。 这里的传播延迟取决于所选的高速缓存类型 (分别对应 watch 操作的传播延迟、高速缓存的 TTL 时长或者 0)。

以环境变量方式使用的 ConfigMap 数据不会被自动更新。 更新这些数据需要重新启动 Pod。

验证

# 修改property_1为Hello_1,property_2为World_1 [root@k8s-deploy yaml]#kubectl apply -f configmap.yaml configmap/configmap-test configured [root@k8s-deploy yaml]#kubectl describe cm configmap-test Name: configmap-test Namespace: default Labels: <none> Annotations: <none> Data ==== property_1: ---- Hello_1 property_2: ---- World_1 BinaryData ==== Events: <none> [root@k8s-deploy yaml]#kubectl exec -it nginx-volume bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@nginx-volume:/# more /tmp/p1 Hello_1 root@nginx-volume:/# more /tmp/p2 World_1

secret

https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/

Secret 是一种加密存储的资源对象,可以将认证信息、证书、私钥等保存在 Secret 中,而不需要把这些敏感数据暴露到镜像或者 Pod 定义中,从而更加安全和灵活。

Secret 与 ConfigMap 非常像,都是 key-value 键值对形式,使用方式也相同,不同的是 Secret 会加密存储,所以适用于存储敏感信息。

应用场景:

  1. 作为挂载到一个或多个容器上的卷 中的文件。
  2. 作为容器的环境变量。
  3. 由 kubelet 在为 Pod 拉取镜像时使用。

注意:

  • Secret 对象的名称必须是合法的 DNS 子域名。
  • 在为创建 Secret 编写配置文件时,可以设置 data​ 与/或 stringData​ 字段。 data​ 和 stringData​ 字段都是可选的。data​ 字段中所有键值都必须是 base64 编码的字符串。如果不希望执行这种 base64 字符串的转换操作,可以选择设置 stringData​ 字段,其中可以使用任何字符串作为其取值。
  • data​ 和 stringData​ 中的键名只能包含字母、数字、-​、_​ 或 .​ 字符。 stringData​ 字段中的所有键值对都会在内部被合并到 data​ 字段中。 如果某个主键同时出现在 data​ 和 stringData​ 字段中,stringData​ 所指定的键值具有高优先级。

secret 挂载流程

image

Base64 编码

Secret 与 ConfigMap 相同,是以键值对形式保存数据,所不同的是在创建时,data 类型 Secret 的 Value 必须使用 Base64 编码。

对字符串进行 Base64 编码,可以直接使用 echo -n 要编码的内容 | base64​命令即可,示例如下:

[root@k8s-deploy yaml]#echo -n "3306" | base64 MzMwNg==

创建 Secret

如下示例中定义的 Secret 中包含两条 Key-Value。

apiVersion: v1 kind: Secret metadata: name: mysecret data: key1: aGVsbG8gd29ybGQ= # "hello world" Base64编码后的值 key2: MzMwNg== # "3306" Base64编码后的值

查看 secret

[root@k8s-deploy yaml]#kubectl apply -f secret.yaml secret/mysecret created [root@k8s-deploy yaml]#kubectl get secret NAME TYPE DATA AGE mysecret Opaque 2 34s [root@k8s-deploy yaml]#kubectl describe secret mysecret Name: mysecret Namespace: default Labels: <none> Annotations: <none> Type: Opaque Data ==== key2: 4 bytes key1: 11 bytes

在环境变量中引用 Secret

Secret 最常见的用法是作为环境变量注入到容器中,如下示例。

apiVersion: v1 kind: Pod metadata: name: env-nginx spec: containers: - image: nginx:1.16.1 name: container-0 resources: limits: cpu: 100m memory: 200Mi requests: cpu: 100m memory: 200Mi env: - name: key valueFrom: secretKeyRef: # 引用Secret name: mysecret key: key1 imagePullSecrets: - name: default-secret

进入 Pod 容器中,可以查看环境变量 key 的值,base64 解码后为 hello world​。

[root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE env-nginx 1/1 Running 0 39s [root@k8s-deploy yaml]#kubectl exec -it env-nginx bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@env-nginx:/# echo $key hello world

在 Volume 中引用 Secret

在 Volume 中引用 Secret,就是通过文件的方式直接将 Secret 的每条数据填入 Volume,每条数据是一个文件,键就是文件名,键值就是文件内容。

如下示例中,创建一个名为 vol-secret 的 Volume,这个 Volume 引用名为 mysecret​的 Secret,再将 Volume 挂载到容器的 /tmp​路径下。Pod 创建成功后,在容器的 /tmp​路径下,就有两个文件 key1 和 key2。

apiVersion: v1 kind: Pod metadata: name: volume-nginx spec: containers: - image: nginx:1.16.1 name: container-0 resources: limits: cpu: 100m memory: 200Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: vol-secret # 挂载名为vol-secret的Volume mountPath: "/tmp" imagePullSecrets: - name: default-secret volumes: - name: vol-secret secret: # 引用Secret secretName: mysecret

进入 Pod 容器中,可以在/tmp 目录下发现 key1 和 key2 两个文件,并看到文件中的值是 base64 解码后的值,分别为 hello world​和 3306​。

[root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE env-nginx 1/1 Running 0 8m6s volume-nginx 1/1 Running 0 4s [root@k8s-deploy yaml]#kubectl exec -it volume-nginx bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@volume-nginx:/# more /tmp/key1 hello world root@volume-nginx:/# more /tmp/key2 3306

secret 类型

创建 Secret 时,可以使用 Secret 资源的 type​ 字段,或者与其等价的 kubectl​ 命令行参数为其设置类型。 Secret 类型有助于对 Secret 数据进行编程处理。

Kubernetes 提供若干种内置的类型,用于一些常见的使用场景。 针对这些类型,Kubernetes 所执行的合法性检查操作以及对其所实施的限制各不相同。

内置类型 用法
Opaque 用户定义的任意数据
kubernetes.io/service-account-token 服务账号令牌
kubernetes.io/dockercfg ~/.dockercfg​ 文件的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json​ 文件的序列化形式
kubernetes.io/basic-auth 用于基本身份认证的凭据
kubernetes.io/ssh-auth 用于 SSH 身份认证的凭据
kubernetes.io/tls 用于 TLS 客户端或者服务器端的数据
bootstrap.kubernetes.io/token 启动引导令牌数据

详细信息查看:https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/#secret-types

三、掌握基于 NFS 实现 pod 数据持久化的使用方式,测试 emptyDir、hostPath 的使用

https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/

NFS

nfs 卷能将 NFS (网络文件系统) 挂载到 Pod 中。nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。

部署 nfs 服务器

主机:10.0.0.101(harbor1)

# 安装nfs服务端 apt install -y nfs-kernel-server nfs-common # 在/etc/exports末尾添加 echo "/data *(rw,sync,no_root_squash,no_subtree_check)" >> /etc/exports # 配置生效 exportfs -r

查看状态

[root@harbor1 ~]#exportfs -v /data <world>(rw,wdelay,no_root_squash,no_subtree_check,sec=sys,rw,secure,no_root_squash,no_all_squash)

创建 NFS 卷

# k8s集群需安装nfs客户端 apt install -y nfs-common

创建 pod

apiVersion: v1 kind: Pod metadata: name: test-pd spec: containers: - image: nginx:1.16.1 name: test-container volumeMounts: - mountPath: /my-nfs-data # 挂载至容器内目录 name: test-volume # 使用挂载卷名称 volumes: - name: test-volume # 定义卷名称 nfs: server: 10.0.0.101 # nfs服务器,可以配置IP,也可配置域名 path: /data # nfs目录,须在nfs挂载目录中 readOnly: true # 只读权限

验证

# nfs服务器/data目录下文件 [root@harbor1 ~]#ls -l /data/ total 0 drwxr-xr-x 2 10000 10000 6 Jan 17 12:09 ca_download drwxr-xr-x 2 10000 10000 6 Jan 17 12:09 chart_storage drwx------ 3 systemd-coredump systemd-coredump 18 Jan 17 12:09 database drwxr-xr-x 2 10000 10000 6 Jan 26 13:45 job_logs drwxr-xr-x 2 systemd-coredump systemd-coredump 22 Jan 26 22:57 redis drwxr-xr-x 3 10000 10000 20 Jan 17 12:46 registry drwxr-xr-x 2 10000 10000 6 Jan 17 12:09 scandata_exports drwxr-xr-x 6 root root 58 Jan 17 12:09 secret drwxr-xr-x 4 root root 34 Jan 17 12:09 trivy-adapter # 进入容器,查看/my-nfs-data目录下文件 [root@k8s-deploy yaml]#kubectl get pod NAME READY STATUS RESTARTS AGE test-pd 1/1 Running 0 4m7s [root@k8s-deploy yaml]#kubectl exec -it test-pd bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@test-pd:/# ls -l /my-nfs-data/ total 0 drwxr-xr-x 2 10000 10000 6 Jan 17 04:09 ca_download drwxr-xr-x 2 10000 10000 6 Jan 17 04:09 chart_storage drwx------ 3 999 999 18 Jan 17 04:09 database drwxr-xr-x 2 10000 10000 6 Jan 26 05:45 job_logs drwxr-xr-x 2 999 999 22 Jan 26 15:02 redis drwxr-xr-x 3 10000 10000 20 Jan 17 04:46 registry drwxr-xr-x 2 10000 10000 6 Jan 17 04:09 scandata_exports drwxr-xr-x 6 root root 58 Jan 17 04:09 secret drwxr-xr-x 4 root root 34 Jan 17 04:09 trivy-adapter # 只读,不可写 root@test-pd:/my-nfs-data# echo 'pod' > 1.log bash: 1.log: Read-only file system

进入 Pod 容器中,可以看到容器/my-nfs-data 目录下文件与 nfs 服务器/data 目录文件相同。

emptydir

当 Pod 分派到某个节点上时,emptyDir​ 卷会被创建,并且在 Pod 在该节点上运行期间,卷一直存在。 就像其名称表示的那样,卷最初是空的。 尽管 Pod 中的容器挂载 emptyDir​ 卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir​ 卷中相同的文件。 当 Pod 因为某些原因被从节点上删除时,emptyDir​ 卷中的数据也会被永久删除。

image

emptydir 示例:

apiVersion: v1 kind: Pod metadata: name: emptydir-pd spec: containers: - image: nginx:1.16.1 name: test-container volumeMounts: - mountPath: /cache name: cache-volume volumes: - name: cache-volume emptyDir: sizeLimit: 100Mi

验证

# 查看pod所在宿主机IP [root@k8s-deploy yaml]#kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES emptydir-pd 1/1 Running 0 4s 10.200.135.212 10.0.0.13 <none> <none> # 进入容器创建emptpydir-test文件 [root@k8s-deploy yaml]#kubectl exec -it emptydir-pd bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@emptydir-pd:/# ls /cache/ root@emptydir-pd:/# echo 'emptydir-pod' >> /cache/emptpydir-test # 进入宿主机,查看emptpydir-test文件内容 [root@k8s-master3 ~]#find / -name emptpydir-test /var/lib/kubelet/pods/c5e8d5a6-f898-4309-baee-d6287e703ae2/volumes/kubernetes.io~empty-dir/cache-volume/emptpydir-test [root@k8s-master3 ~]#cat /var/lib/kubelet/pods/c5e8d5a6-f898-4309-baee-d6287e703ae2/volumes/kubernetes.io~empty-dir/cache-volume/emptpydir-test emptydir-pod # 删除容器,宿主机emptpydir-test文件也跟随删除 [root@k8s-deploy yaml]#kubectl delete -f emptydir-pd.yaml pod "emptydir-pd" deleted [root@k8s-deploy yaml]#kubectl get pod No resources found in default namespace. [root@k8s-master3 ~]#cat /var/lib/kubelet/pods/c5e8d5a6-f898-4309-baee-d6287e703ae2/volumes/kubernetes.io~empty-dir/cache-volume/emptpydir-test cat: /var/lib/kubelet/pods/c5e8d5a6-f898-4309-baee-d6287e703ae2/volumes/kubernetes.io~empty-dir/cache-volume/emptpydir-test: No such file or directory

创建 pod 后生成 emptydir 本地临时卷,删除 pod 后 emptydir 本地临时卷被回收。

hostpath

hostPath​ 卷能将主机节点文件系统上的文件或目录挂载到 Pod 中。 pod 删除时,hostpath 卷不会删除。

注意

  • HostPath 卷存在许多安全风险,最佳做法是尽可能避免使用 HostPath。 当必须使用 HostPath 卷时,它的范围应仅限于所需的文件或目录,并以只读方式挂载。
  • 如果通过 AdmissionPolicy 限制 HostPath 对特定目录的访问,则必须要求 volumeMounts​ 使用 readOnly​ 挂载以使策略生效。

​**hostPath 应用场景:**​

  • 运行一个需要访问 Docker 内部机制的容器;可使用 hostPath​ 挂载 /var/lib/docker​ 路径。
  • 在容器中运行 cAdvisor 时,以 hostPath​ 方式挂载 /sys​。
  • 允许 Pod 指定给定的 hostPath​ 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

除了必需的 path​ 属性之外,可选择为 hostPath​ 卷指定 type​。

type 值参考:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#hostpath

hostpath 示例:

apiVersion: v1 kind: Pod metadata: name: hostpath-pd spec: containers: - image: nginx:1.16.1 name: test-container volumeMounts: - mountPath: /hostpath-pd # 容器中挂载位置 name: hostpath-volume volumes: - name: hostpath-volume hostPath: # 宿主上目录位置 path: /data

验证

# 查看pod所在宿主机IP [root@k8s-deploy yaml]#kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES hostpath-pd 1/1 Running 0 2s 10.200.135.214 10.0.0.13 <none> <none> # 进入容器,创建hostpath-test文件 [root@k8s-deploy yaml]#kubectl exec -it hostpath-pd bash kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead. root@hostpath-pd:/# echo 'hostpath' >> /hostpath-pd/hostpath-test # 进入宿主机,查看hostpath-test文件内容 [root@k8s-master3 data]#cat /data/hostpath-test hostpath # 删除容器 [root@k8s-deploy yaml]#kubectl delete -f hostpath-pd.yaml pod "hostpath-pd" deleted [root@k8s-deploy yaml]#kubectl get pod No resources found in default namespace. # 宿主机hostpath-test文件依然存在,未被删除 [root@k8s-master3 data]#cat /data/hostpath-test hostpath

创建 pod 后挂载 hostpath 本地存储卷,删除 pod 后 hostpath 本地存储卷不会删除。

四、实现基于 Secret 实现 nginx 的 tls 认证、并实现私有仓库镜像的下载认证

https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/#tls-secret

tls 认证

自签名证书,创建 secret

mkdir -p /data/certs cd /data/certs openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 3560 -nodes -subj '/CN=www.ca.com' openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=www.mysite.com' openssl x509 -req -sha256 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt # 创建secret kubectl create secret tls myserver-tls-key --cert=./server.crt --key=./server.key -n myserver

查看 secret

[root@k8s-deploy certs]#kubectl get secret -n myserver NAME TYPE DATA AGE myserver-tls-key kubernetes.io/tls 2 3m48s [root@k8s-deploy certs]#kubectl describe secret myserver-tls-key -n myserver Name: myserver-tls-key Namespace: myserver Labels: <none> Annotations: <none> Type: kubernetes.io/tls Data ==== tls.crt: 1667 bytes tls.key: 3272 bytes

创建 web 服务 nginx 并使用证书

# 创建configmap apiVersion: v1 kind: ConfigMap metadata: name: nginx-config namespace: myserver data: default: | server { listen 80; listen 443 ssl; server_name www.mysite.com; ssl_certificate /etc/nginx/conf.d/certs/tls.crt; ssl_certificate_key /etc/nginx/conf.d/certs/tls.key; location / { root /usr/share/nginx/html; index index.html index.htm; if ($scheme = http) { rewrite / https://www.mysite.com permanent; } #if (-e $request_filename) { # rewrite ^/(.*) /index.html last; #} } } --- # 创建deployment apiVersion: apps/v1 kind: Deployment metadata: name: myserver-nginx-deploy namespace: myserver labels: app: myserver-nginx-deploy spec: replicas: 3 selector: matchLabels: app: myserver-nginx template: metadata: labels: app: myserver-nginx spec: containers: - name: myserver-nginx image: nginx:1.19.1 ports: - containerPort: 80 volumeMounts: - name: nginx-config # nginx-config卷名称 mountPath: /etc/nginx/conf.d # 容器中挂载所在目录 - name: myserver-tls-key # myserver-tls-key名称 mountPath: /etc/nginx/conf.d/certs # 容器中挂载所在目录 volumes: - name: nginx-config # 定义卷名称 configMap: # 引用configmap name: nginx-config # 对应ConfigMap中名称 items: - key: default # ConfigMap中default键 path: mysite.conf # 挂载文件名称,文件内容为default的值 - name: myserver-tls-key secret: # 引用secret secretName: myserver-tls-key # 未设置itmes,默认使用所有itmes中key、path数据,key(如secret中tls.crt值)为文件内容,path为文件名(tls.crt) --- # 创建service apiVersion: v1 kind: Service metadata: name: nmyserver-nginx-service namespace: myserver spec: type: NodePort selector: app: myserver-nginx ports: - name: http # 名称http protocol: TCP # TCP协议 port: 80 # Service端口 targetPort: 80 # pod端口 nodePort: 30019 # 宿主机端口 - name: https # 名称https protocol: TCP port: 443 targetPort: 443 nodePort: 30020

查看状态

[root@k8s-deploy yaml]#kubectl apply -f myserver-nginx.yaml configmap/nginx-config created deployment.apps/myserver-nginx-deploy created service/nmyserver-nginx-service created [root@k8s-deploy yaml]#kubectl get svc -n myserver NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nmyserver-nginx-service NodePort 10.100.79.198 <none> 80:30019/TCP,443:30020/TCP 15s [root@k8s-deploy yaml]#kubectl get pod -n myserver -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myserver-nginx-deploy-77fd49884f-hnntn 1/1 Running 0 25s 10.200.169.154 10.0.0.42 <none> <none> myserver-nginx-deploy-77fd49884f-p96p4 1/1 Running 0 25s 10.200.107.214 10.0.0.43 <none> <none> myserver-nginx-deploy-77fd49884f-x7lcv 1/1 Running 0 25s 10.200.135.216 10.0.0.13 <none> <none>

测试,https 访问集群任一主机 IP:30020

image

配置负载均衡

#vim /etc/haproxy/haproxy.cfg # 文件末尾添加如下配置 ... listen myserver_nginx_http_80 bind 10.0.0.10:80 mode tcp server 10.0.0.11 10.0.0.11:30019 check inter 3s fall 3 rise 5 server 10.0.0.12 10.0.0.12:30019 check inter 3s fall 3 rise 5 server 10.0.0.13 10.0.0.13:30019 check inter 3s fall 3 rise 5 server 10.0.0.41 10.0.0.41:30019 check inter 3s fall 3 rise 5 server 10.0.0.42 10.0.0.42:30019 check inter 3s fall 3 rise 5 server 10.0.0.43 10.0.0.43:30019 check inter 3s fall 3 rise 5 listen myserver_nginx_https_443 bind 10.0.0.10:443 mode tcp balance source #源地址hash server 10.0.0.11 10.0.0.11:30020 check inter 3s fall 3 rise 5 server 10.0.0.12 10.0.0.12:30020 check inter 3s fall 3 rise 5 server 10.0.0.13 10.0.0.13:30020 check inter 3s fall 3 rise 5 server 10.0.0.41 10.0.0.41:30020 check inter 3s fall 3 rise 5 server 10.0.0.42 10.0.0.42:30020 check inter 3s fall 3 rise 5 server 10.0.0.43 10.0.0.43:30020 check inter 3s fall 3 rise 5

查看端口

# 重启haproxy systemctl reload haproxy.service [root@k8s-ha1 ~]#ss -ntl|grep 10.0.0.10: LISTEN 0 4096 10.0.0.10:6443 0.0.0.0:* LISTEN 0 4096 10.0.0.10:80 0.0.0.0:* LISTEN 0 4096 10.0.0.10:443 0.0.0.0:*

验证

  • 配置 host 域名解析
10.0.0.10 www.mysite.com
  • 浏览器访问 http://www.mysite.com,自动跳转 https

image

  • 查看自签名证书

image

  • 进入首页

image

私有仓库认证

创建 sercet

  • 使用命令创建
kubectl create secret docker-registry keyName \ --docker-server=registry.cn-shanghai.aliyuncs.com \ --docker-username=USER \ --docker-password=PASSWORD
  • 使用 docker 认证文件创建
# 登录私有仓库,登录成功后,认证信息保存至/root/.docker/config.json文件 docker login --username=USER registry.cn-shanghai.aliyuncs.com # 阿里云账号名 # 创建secret kubectl create secret generic aliyun-registry-image-pull-key \ --from-file=.dockerconfigjson=/root/.docker/config.json \ --type=kubernetes.io/dockerconfigjson \ -n myserver

查看 secret

# 查看secret [root@k8s-deploy yaml]#kubectl get secret -n myserver NAME TYPE DATA AGE aliyun-registry-image-pull-key kubernetes.io/dockerconfigjson 1 59s myserver-tls-key kubernetes.io/tls 2 2h # 查看aliyun-registry-image-pull-key secret信息 [root@k8s-deploy yaml]#kubectl describe secret aliyun-registry-image-pull-key -n myserver Name: aliyun-registry-image-pull-key Namespace: myserver Labels: <none> Annotations: <none> Type: kubernetes.io/dockerconfigjson Data ==== .dockerconfigjson: 162 bytes # 查看aliyun-registry-image-pull-key secret内容 [root@k8s-deploy yaml]#kubectl get secret aliyun-registry-image-pull-key -n myserver -oyaml apiVersion: v1 data: .dockerconfigjson: ewoJIFTbj......iCgkJfQoJfQp9 kind: Secret metadata: creationTimestamp: "2023-01-27T11:03:52Z" name: aliyun-registry-image-pull-key namespace: myserver resourceVersion: "626544" uid: d69009a9-c89a-45d4-8e90-ab5f36ce9a3b type: kubernetes.io/dockerconfigjson

上传镜像至阿里云私有仓库

[root@k8s-deploy yaml]#docker tag nginx:1.18.0 registry.cn-shanghai.aliyuncs.com/shichu/baseimages:nginx-1.18.0 [root@k8s-deploy yaml]#docker push registry.cn-shanghai.aliyuncs.com/shichu/baseimages:nginx-1.18.0 The push refers to repository [registry.cn-shanghai.aliyuncs.com/shichu/baseimages] 4fa6704c8474: Pushed 4fe7d87c8e14: Pushed 6fcbf7acaafd: Pushed f3fdf88f1cb7: Pushed 7e718b9c0c8c: Pushed nginx-1.18.0: digest: sha256:9b0fc8e09ae1abb0144ce57018fc1e13d23abd108540f135dc83c0ed661081cf size: 1362

创建 web 服务

使用 secret 认证,登录私有仓库并下载 nginx 镜像

apiVersion: apps/v1 kind: Deployment metadata: name: myserver-myapp-frontend-deployment namespace: myserver spec: replicas: 1 selector: matchLabels: app: myserver-myapp-frontend template: metadata: labels: app: myserver-myapp-frontend spec: containers: - name: myserver-myapp-frontend image: registry.cn-shanghai.aliyuncs.com/shichu/baseimages:nginx-1.18.0 ports: - containerPort: 80 imagePullSecrets: - name: aliyun-registry-image-pull-key --- apiVersion: v1 kind: Service metadata: name: myserver-myapp-frontend namespace: myserver spec: ports: - name: http port: 80 targetPort: 80 nodePort: 30021 protocol: TCP type: NodePort selector: app: myserver-myapp-frontend

验证

下载阿里云私有仓库镜像,创建 web 服务

# 查看pod [root@k8s-deploy yaml]#kubectl get pod -n myserver -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myserver-myapp-frontend-deployment-6559868768-t99rl 1/1 Running 0 29s 10.200.107.221 10.0.0.43 <none> <none> # service root@k8s-deploy yaml]#kubectl get svc -n myserver -owide NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR myserver-myapp-frontend NodePort 10.100.47.93 <none> 80:30021/TCP 45s app=myserver-myapp-frontend # 查看创建pod信息,下载阿里云私有仓库镜像 [root@k8s-deploy yaml]#kubectl describe pod myserver-myapp-frontend-deployment-6559868768-t99rl -n myserver ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 81s default-scheduler Successfully assigned myserver/myserver-myapp-frontend-deployment-6559868768-t99rl to 10.0.0.43 Normal Pulling 81s kubelet Pulling image "registry.cn-shanghai.aliyuncs.com/shichu/baseimages:nginx-1.18.0" Normal Pulled 80s kubelet Successfully pulled image "registry.cn-shanghai.aliyuncs.com/shichu/baseimages:nginx-1.18.0" in 1.311082284s Normal Created 80s kubelet Created container myserver-myapp-frontend Normal Started 80s kubelet Started container myserver-myapp-frontend

浏览器访问,

image

  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...