查看日志
kubectl logs nginx
kubectl logs nginx --all-containers=true
kubectl logs -lapp=nginx --all-containers=true
kubectl logs -p -c ruby web-1
kubectl logs -f -c ruby web-1
kubectl logs -f -lapp=nginx --all-containers=true # -l后可以空格也可以不空
kubectl logs --tail=20 nginx
kubectl logs --since=1h nginx
调试pod
- kubectl describe pod myapp-pod # 看pod的启动信息
- kubectl logs myapp-pod -c pod # 查看pod中指定的container
pod相关命令
- kubectl delete pod myapp-pod # 删除Pod
- kubectl get pod -o wide # 查看详细信息
- kubectl get pods -w # 持续观察
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
version: v1
spec:
containers:
- name: app
image: nginx
initContainers demo
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh','-c','echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox
command: ['sh','-c','until nslookup myservice; do echo waiting for myserivce; sleep 2; done;']
- name: init-mydb
image: busybox
command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
- initContainers会在创建container之前执行,并且只有执行成功后才会执行container,而且为顺序执行
- 此demo为解析myservice和mydb两个service,如果没有就等着延迟两秒
- 创建两个service
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
- - -
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
原理:
- 在pod启动过程中,init容器会按顺序在网络和数据卷(pause容器,是一个很小的容器,负责网络和数据集的容器)初始化之后启动,每个容器必须在下一个容器启动之前成功退出
- 如果由于运行时或退出失败,将导致容器启动失败,它会根据Pod的restartPolicy指定的策略进行重试。然而,如果Pod的restartPolicy设置为Always,Init容器失败时会使用RestartPolicy策略
- 在所有的Init容器没有成功之前,Pod将不会变成Ready状态。Init容器的端口不会再Service中进行聚集。(容器没成功启动,肯定不能被外界访问)
- 如果Pod重启,所有的Init容器必须重新执行(init容器必须为幂等状态,每次结果都相同)
- 对Init容器spec的修改被限制在容器image字段,修改其他字段都不会生效。更改Init容器的image字段,等于重启该Pod
- Init容器具有应用容器的所有字段。除了readinessProbe,因为init容器无法定义不同于完成的就绪之外的其他状态。这会在验证过程中强制执行(Init只能为完成状态)
- 在Pod中的每个app和Init容器的名称必须唯一;与任何其他容器共享同一个名称,会在验证时抛出错误(名称必须全局唯一)
容器探针
概念:
探针由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用由容器实现的Handler。有三种类型的处理程序
- ExecAction: 在容器内执行指定命令。如果命令退出时返回码为0,则诊断成功
- TCPSocketAction: 对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为成功
- HTTPGetAction: 对指定的端口和路径上的容器的IP地址执行HTTP GET请求。如果响应的状态码大于等于200且小于400,则诊断成功
诊断结果:
- 成功
- 失败
- 未知
两种探测方式:
- livenessProbe: 指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success
- readinessProbe:
指示容器所否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的Ip地址。初始延迟之前的就绪状态默认为Failture。如果容器不提供就绪探针,则默认状态为Success
就绪监测demo
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget-pod
namespace: default
spec:
containers:
- name: readiness-httpget-container
image: nginx
imagePullPolicy: IfNotPresent
readinessProbe:
httpGet:
port: 80
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
- initialDelaySeconds: 一秒之后监测
- periodSeconds: 多秒后监测
命令:进入容器
- kubectl exec podname -c containername -it -- /bin/sh
存活监测
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
spec:
containers:
- name: liveness-exec-container
image: nginx
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","touch /tmp/live; sleep 60; rm -rf /tmp/live; sleep 3600"]
livenessProbe:
exec:
command: ["test","-e","/tmp/live"]
initialDelaySeconds: 1
periodSeconds: 3
说明:IfNotPresent策略为本地没有的镜像则去远端拉取,哪怕是latest标签的,也会先从本地先读取,没有再去拉
httpGet
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-pod
spec:
containers:
- name: liveness-httpget-container
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1
periodSeconds: 3
timeoutSeconds: 10
tcp
apiVersion: v1
kind: Pod
metadata:
name: probe-tcp
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
livenessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 8080
periodSeconds: 3
启动退出
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh","-c","echo Hello from the postStart Handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
pod的状态
- Pending:Pod已被kubernetes接受,但有一个或多个容器尚未被创建,等待时间包括Pod的时间和通过网络下载镜像的时间,这可能需要花点时间
- Running:该Pod已经绑定到了一个节点上,Pod中所有的容器都已经被创建,至少有一个容器正在运行,或者正处于启动或重启的状态
- Succeeded:Pod中的所有容器都被成功终止,并且不会再重启
- Failed:Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止
- Unknown:因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败
Pod控制器
- ReplicationController 和 ReplicaSet
- Deployment
- DaemonSet
- StateFulSet
- Job/CronJob
- Horizontal Pod Autoscaling
ReplicationController 和 ReplicaSet
- RC和RS都支持确保容器应用的副本数保持在用户定义的副本数,如果容器异常退出,则自动创建新的pod来替代,多出来的容器自动回收
- RS支持集合式selector选择(标签)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- kubectl scale deployment nginx-deployment --replicas=10 # 扩容,但不会改变rs
- kubectl set image deployment/nginx-deployment nginx=busybox # 更新镜像会新增rs
- kubectl rollout undo deployment/nginx-deployment [--to-revision=2]# 回滚[到第二个版本]
- kubectl get pod --show-labels # 查看Pod的标签
- kubectl label pod podname tier=fronted1 --overwrite=True # 修改pod的标签
- kubectl rollout status deployments deployment-name # 查看回滚的状态
- kubectl rollout history deployment/deployment-name # 查看deployment-name的回滚历史记录
- kubectl rollout pause deployment/deployment-name # 暂停
Deployment
- 申明式编程 apply
- 命令式编程 create
- Deployment为Pod和ReplicaSet提供了一个声明式定义方法,用来替代以前的RC来方便的管理应用
- 定义Deployment来创建Pod和RS
- 滚动升级和回滚应用
- 扩容缩
- 暂停和继续Deployment
DaemonSet
确保全部Node上运行一个Pod脚本,当有Node加入集群时,也会为他们新增一个Pod。当有Node从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod
- 运行集群存储daemon
- 在每个Node上运行日志收集daemon
- 在每个Node上运行监控daemon
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-example
labels:
app: daemonset
spec:
selector:
matchLabels:
name: daemonset-example
template:
metadata:
labels:
name: daemonset-example
spec:
containers:
- name: daemonset-example
image: nginx
Job
Job负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束
CronJob
CronJob管理基于时间的Job
- 在给定时间点只运行一次
- 周期性运行的Job,例如:数据库备份,发送邮件
cronjob spec - RestartPolicy仅支持Never或OnFaliure
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
StatefulSet
statefulset作为Controller为Pod提供唯一的标识。它可以保证部署和scale的顺序
statefulset是为了解决有状态服务的问题
- 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
- 稳定的网络标识,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
- 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
- 有序收缩,有序删除(从N-1到0)
HPA 自动扩容
apiVersion
- kubectl api-versions # 查看apiServer版本
各种apiVersion的含义
alpha
* 该软件可能包含错误。启用一个功能可能会导致bug
* 随时可能会丢弃对该功能的支持,恕不另行通知
beta
* 软件经过很好的测试。启用功能被认为是安全的。
* 默认情况下功能是开启的
* 细节可能会改变,但功能在后续版本不会被删除
stable
* 该版本名称命名方式:vX这里X是一个整数
* 稳定版本、放心使用
* 将出现在后续发布的软件版本中
v1
Kubernetes API的稳定版本,包含很多核心对象:pod、service等
apps/v1beta2
在kubernetes1.8版本中,新增加了apps/v1beta2的概念,apps/v1beta1同理
DaemonSet,Deployment,ReplicaSet 和 StatefulSet的当时版本迁入apps/v1beta2,兼容原有的extensions/v1beta1
apps/v1
在kubernetes1.9版本中,引入apps/v1,deployment等资源从extensions/v1beta1, apps/v1beta1 和 apps/v1beta2迁入apps/v1,原来的v1beta1等被废弃。
apps/v1代表:包含一些通用的应用层的api组合,如:Deployments, RollingUpdates, and ReplicaSets
batch/v1
代表job相关的api组合
在kubernetes1.8版本中,新增了batch/v1beta1,后CronJob 已经迁移到了 batch/v1beta1,然后再迁入batch/v1
autoscaling/v1
代表自动扩缩容的api组合,kubernetes1.8版本中引入。
这个组合中后续的alpha 和 beta版本将支持基于memory使用量、其他监控指标进行扩缩容
extensions/v1beta1
deployment等资源在1.6版本时放在这个版本中,后迁入到apps/v1beta2,再到apps/v1中统一管理
certificates.k8s.io/v1beta1
安全认证相关的api组合
authentication.k8s.io/v1
资源鉴权相关的api组合
SVC
- ClusterIp: 默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
- NodePort: 在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodePort来访问该服务
- LoadBalancer: 在NodePort的基础上,借助cloud provider创建一个外部负载均衡器,并将请求转发到NodePort上
- ExternalName: 把集群外部的服务引入到集群内部中,在集群内部直接使用。没有任何类型代理被创建
实现:
Nginx(172.24.3.123) -> ClusterIP,Port(10.0.0.123:9098) -> WebApp-1 WebApp-2 WebApp-3
- apiserver 用户通过kubectl命令向apiserver发送创建service命令,apiserver接收到请求后将数据存储到etcd
- kube-proxy kubernetes的每个节点中都有一个叫做kube-proxy的进程,这个进程负责感知servie,pod的变化,并将变化的信息写入本地的iptables规则中
- iptables使用NAT等技术将virtualIp的流量转至endpoint中
clusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deploy
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
release: stabel
template:
metadata:
labels:
app: myapp
release: stabel
env: test
spec:
containers:
- name: myapp
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: ClusterIP
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
targetPort: 80
Headless Service
有时不需要或不想要负载均衡,以及单独的Service IP,遇到这种情况,可以通过指定Cluster IP的值为None,来创建Headless Service,这类Service并不会分配Cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由
kubectl get pods -n kube-system -o wide
dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.2
apiVersion: v1
kind: Service
metadata:
name: myapp-headless
namespace: default
spec:
selector:
app: myapp
ClusterIP: "None"
ports:
- port: 80
targetPort: 80
NodePort
apiVersion: v1
kind: Service
metadata:
name: myapp
namespace: default
spec:
type: NodePort
selector:
app: myapp
release: stabel
ports:
- name: http
port: 80
targetPort: 80
ExternalName
这种类型的Service通过返回CNAME和它的值,可以将服务映射到externalName字段的内容(例如:hub.atguigu.com).ExternalName Service 是Service的特例,没有selector,也没有定义任何的端口和Endpoint.相反,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
kind: Service
apiVersion: v1
metadata:
name: my-service-1
namespace: default
spec:
type: ExternalName
externalName: my.database.example.com
指令:
kubectl get pods -n kube-system -o wide
dig -t A my-service-1.default.svc.cluster.local @10.244.0.3
my-service-1.default.svc.cluster.local. 30 IN CNAME my.database.example.com.
Ingress
HTTP代理访问
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-dm
spec:
replicas: 2
selector:
matchLabels:
name: nginx
template:
metadata:
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
name: nginx
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
- kubectl get svc -n ingress-nginx # 获取ingress的svc信息
找到对应端口,然后域名加端口访问
HTTPS代理访问
生成私钥和证书
- openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/0=nginxsvc"
创建cert存储
kubectl create secret tls tls-secret --key tls.key --cert tls.crt
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-test
spec:
tls:
- hosts:
- foo.bar.com
secretName: tls-secret
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
说明:
- kubectl get deployment # 会有普通的deployment
- kubectl get svc # 会有普通的svc
- kubectl get ingress # 会有Ingress
- kubectl get svc -n ingress-nginx # 会有http和https端口,直接访问域名+端口就ok了
Nginx进行BasicAuth
- apt install apache2-utils
- htpasswd -c auth foo
- kubectl create secret generic basic-auth --from-file=auth
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-with-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
Nginx re
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://foo.bar.com:31795
spec:
rules:
- host: foo10.bar.com
http:
paths:
- path: /
backend:
serviceName: nginx-svc
servicePort: 80
存储
ConfigMap
configMap,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API给我们提供了向容器中注入配置信息的机制,ConfigMap可以用来保存单个属性,也可以用来保存整个配置文件或者json二进制对象
1.使用目录创建
game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passpharase=UUDDLRLRBABAS
ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
- kubectl create configmap game-config --from-file=../dir
- kubectl describe cm xxx
- kubectl get cm xxx -o yaml
2.使用单文件创建
同上,把目录换成文件名
3.使用字面值创建
使用文字值创建,利用-from-literal参数传递配置信息
kubectl create configmap special-config --from-literal=special.how=very --from-literal-special.type=charm
代替环境变量
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
---
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: nginx
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","env"]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.type
envFrom:
- configMapRef:
name: env-config
restartPolicy: Never
在数据卷里面使用这个ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: nginx
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","cat /etc/config/special.how"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
restartPolicy: Never
configMap热更新
apiVersion: v1
kind: ConfigMap
metadata:
name: log-config
data:
log_level: INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 1
selector:
matchLabels:
run: my-nginx
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: log-config
- kubectl edit configmap log-config
secret
Opaque类型的数据是一个map类型,要求value是base64编码格式:
echo -n "admin" | base64
echo -n "123456" | base64
secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: YWRtaW4=
username: MTIzNDU2
1.将Secret挂载到Volume中
apiVersion: v1
kind: Pod
metadata:
labels:
name: seret-test
name: seret-test
spec:
volumes:
- name: secrets
secret:
secretName: mysecret
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: db
volumeMounts:
- name: secrets
mountPath: "/etc/secrets"
readOnly: true
2.将Secret导入到环境变量中
apiVersion: apps/v1
kind: Deployment
metadata:
name: pod-deployment
spec:
selector:
matchLabels:
app: pod-deployment
replicas: 2
template:
metadata:
labels:
app: pod-deployment
spec:
containers:
- name: pod-1
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
env:
- name: TEST_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: TEST_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
3.使用Kubectl 创建docker registry认证的secret
kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
在创建Pod的时候,通过imagePullSecrets来引用刚创建的myregistrykey
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
- name: foo
image: nginx
imagePullSecrets:
- name: myregistrykey
volume
emptyDir
当Pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在,正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除Pod时,emptyDir中的数据将被永久删除
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
hostpath
hostpath卷将主机节点的文件系统中的文件或目录挂载到集群中
用途:
- 运行需要访问Docker内部的容器,使用/var/lib/docker的hostPath
- 在容器中运行cAdvisor;使用/dev/cgroups的hostPath
除了所需的path属性之外,用户还可以为hostpath卷指定type
- 空:空字符串默认用于向后兼容,这意外着在挂载hostPath卷之前不会执行任何检查
- DirectoryOrCreate:如果给定的路径上没有任何东西存在,那么将根据需要在哪里创建一个空目录,权限设置为0755,与kubelet具有相同的组合所有权
- Directory: 给定的路径必须存在目录
- FileOrCreate:如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为0644,与kubelet具有相同的组和所有权
- File:给定的路径下必须存在文件
- Socket:给定的路径下必须存在UNIX套接字
- CharDevice:给定的路径下必须存在字符设备
- BlockDevice: 给定的路径下必须存在块设备
当Kubernetes按照计划添加资源感知调度时,将无法考虑hostPath使用的资源。在底层主机上创建的文件或目录只能由root写入,您需要在特权容器中以root身份运行进程,或修改主机上的文件权限以便写入hostPath卷
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: nginx
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
path: /data
type: Directory
PV
概念:
PersistenVolume(PV)
是由管理员设置的存储,它是集群的一部分。就像节点是集群中的资源一样,PV也是集群中的资源。PV是Volume之类的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS,iSCSI或特定于云供应商的存储系统
PersistemVolumeClaim(PVC)
是用户存储的请求。它与Pod相似。Pod消耗节点资源。PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式
静态pv
集群管理员创建一些PV。它们带有可供集群用户使用的实际存储细节。它们存在于Kubernetes Api中,可用于消费
绑定:
master中的控制环路监视新的PVC,寻找匹配的PV,并将它们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将该PV绑定到PVC,否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦PV和PVC绑定后。将是排他性,是一一对应的
PV访问模式
PersistenVoule可以以资源提供者支持的任何方式挂载到主机上,如下表所示,供应商具有不同的功能,每个PV的访问模式都将被设置为该卷支持的特定模式
- ReadWriteOnce--该卷可以被单个节点以读/写模式挂载RWO
- ReadOnlyMany--该卷可以被多个节点以只读模式挂载ROM
- ReadWriteMany--该卷可以被多个节点以读/写模式挂载RWM
回收策略
- Retain(保留)--手动回收
- Recycle(回收)--基本擦除(rm -rf /thevolume/*)
- Delete(删除)--关联的存储资产(例如AWS EBS。。。)
状态
卷可处于一下的某种状态:
- Available(可用) -- 一块空闲资源还没有被任何声明绑定
- Bound(已绑定) --卷已经被声明绑定
- Released(已释放) --声明被删除,但是资源还未被集群重新声明
- Failed(失败) -- 该卷的自动回收失败
持久化演示说明-NFS
1.安装NFS服务器
yum install -y nfs-common nfs-utils rpcbind
mkdir /nfsdata
chmod 777 /nfsdata
chown nfsnobody /nfsdata
cat /etc/exports/nfsdata *(rw,no_root_squash.no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs
2.部署PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfspv1
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs
nfs:
path: /data/nfs
server: 10.66.66.10
3.创建服务并使用PVC
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: Statefulset
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumesClaimTemplates:
- metadata:
name: www
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 1Gi
- kubectl edit pv xxx 删除ClaimRef手动清除
Scheduler
简介
scheduler 是kubernetes的调度器,主要的任务是把定义的pod分配到集群的节点上
- 公平:如何保证每个节点都能被分配资源
- 资源高效利用:集群所有资源最大化使用
- 效率:调度的性能要好,能够尽快地对大批量的pod完成调度工作
- 灵活:允许用户根据自己的需求控制调度的逻辑
Scheduler是作为单独的程序运行的,启动之后会一直坚挺API Server,获取PodSpec.NodeName为空的pod,对每个pod都会创建一个binding,表明该pod应该放到哪个节点上
调度过程
调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为predicate;然后对通过的节点按照优先级排序,这个priority;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误
Predicate有一系列的算法可以使用:
- PodFitsResources:节点上剩余的资源是否大于pod请求的资源
- PodFitHost:如果Pod指定了NodeName,检查节点名称是否和NodeName匹配
- PodFitsHostPorts:节点上已经使用的port是否和pod申请的port冲突
- PodSelectorMatches:过滤掉和pod指定的label不匹配的节点
- NoDiskConflict: 已经mount的volume和pod指定的volume不冲突,除非它们都是只读的
如果在predicate过程中没有合适的节点,pod会一直在pending状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续priorites过程:按照优先级大小对节点排序
优先级由一系列键值对组成,键时该优先级项的名称,值是它的权重。这些优先级选项包括:
- LeastRequestedPrioity:通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点
- BalancedResourceAllocation:节点上CPU和Memory使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用
- ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高
通过算法对所有的优先级项目和权重进行计算,得出最终的结果
节点亲和性
pod.spec.nodeAffinity
- preferredDuringSchedulingIgnoredDuringExecution:软策略
- requiredDuringSchedulingIgnoredDuringExecution:硬策略
硬策略
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoreDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- k8s-node2
- kubectl get node --show-labels # 查看node的标签
软策略
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: nginx
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoreDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: source
operator: In
values:
- qikqiak
键值运算关系
- In: label的值在某个列表中
- NotIn: label的值不在某个列表中
- Gt:label的值大于某个值
- LT:label的值小于某个值
- Exists:某个label存在
- DoesNotExist:某个label不存在
Pod亲和性
pod.spec.affinity.podAffinity/podAntiAffinity
- preferredDuringSchedulingIgnoredDuringExecution: 软策略
- requiredDuringSchedulingIgnoredDuringExecution:硬策略
apiVersion: v1
kind: Pod
metadata:
name: pod-3
labels:
app: pod-3
spec:
containers:
- name: pod-3
image: nginx
affinity:
podAffinity:
requiredDuringSchedulingIgnoreDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- pod-1
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoreDuringExecution:
- weight: 1
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- pod-2
topologyKey: kubernetes.io/hostname
亲和性/反亲和性调度策略比较
调度策略
调度策略 | 匹配标签 | 操作符 | 拓扑域支持 | 调度目标 |
---|---|---|---|---|
nodeAffinity | 主机 | In,NotIn,Exists,DoesNotExist,Gt,Lt | 否 | 指定主机 |
podAffinity | POD | In,NotIn,Exists,DoesNotExist | 是 | POD与指定POD同一拓扑域 |
podAnitAffinity | POD | In,NotIn,Exists,DoesNotExist | 是 | POD与指定POD不在同一拓扑域 |
Taint和Toleration
节点亲和性,是pod的一种属性,它使pod被吸引到一类的节点。Taint则相反,它使节点能够排斥一类特定的pod
Taint和toleration相互配合,可以用来避免pod被分配到不合适的节点上,每个节点都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的pod,是不会被该节点接收的,如果将toleration应用于pod上,则表示这些pod可以被调度到具有匹配taint的节点上
污点(Taint)
1.污点的组成
使用kubectl taint命令可以给某个Node节点设置污点,Node被设置上污点之后就和Pod之间存在了一种相斥的关系,可以让Node拒绝Pod的调度执行,甚至将Node已经存在的Pod驱逐出去
每个污点的组成如下:
key=value:effect
每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用。当前taint effect支持如下三个选项
- NoSchedule:表示k8s不会将Pod调度到具有该污点的Node上
- PreferNoSchedule:表示k8s将尽量避免将Pod调度到具有该污点的Node上
- Noexecute:表示k8s将不会将Pod调度到具有该污点的Node上,同时会将Node上已经存在的Pod驱逐出去
- 污点的设置,查看和去除
# 设置污点
kubectl taint nodes node1 key1=value:NoSchedule
# 节点说明中,查看Taints字段
kubectl describe pod pod-name
# 去除污点
kubectl taint nodes node1 key1=value:NoSchedule-
容忍
设置了污点的Node将根据taint的effect:NoSchedule PreferNoSchedule NoExecute 和pod之间产生互斥的关系,Pod将在一定程度上不会被调度到Node上。但我们可以再Pod上设置容忍,意思是设置了容忍的Pod将可以容忍污点的存在,可以被调度到存在污点的Node上
pod.spec.tolerations
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerationSeconds: 3600
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
- key: "key2"
operator: "Exists"
effect: "NoSchedule"
- 其中key,vaule,effect要与Node上设置的taint保持一致
- operator的值为Exists将会忽略vaule值
- tolerationSeconds用于描述当pod需要被驱逐时可以再Pod上继续保持运行的时间
- 当不指定key值时,表示容忍所有的污点key:
tolerations:
- operator: "Exists"
2.当不指定effect值时,表示容忍所有污点作用
tolerations:
- key: "key"
operator: "Exists"
3.有多个Master存在时,防止资源浪费,可以如下设置
kubectl taint nodes Node-name node-role.kubernetes.io/master=:PreferNoSchedule
指定调度节点
1.Pod.spec.nodeName将Pod直接调度到指定的Node节点上,会跳过Scheduler的调度策略,该匹配规则是强制匹配
apiVersion: apps/v1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 7
template:
metadata:
labels:
app: myweb
spec:
nodeName: k8s-node01
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80
2.Pod.spec.nodeSelector: 通过Kubernetes的label-selector机制选择节点,调度器调度策略匹配label,而后调度Pod到目标节点,该匹配规则属于强制约束
apiVersion: apps/v1
kind: Deployment
metadta:
name: myweb
spec:
replicas: 2
selector:
labelMatch:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
nodeSelector:
disk: ssd
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80
- kubectl label node k8s-node01 disk=ssd
安全认证
kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Sever是集群内部各个组件通信的中介,也是外部控制的入口。所以Kubernetes的安全机制基本就是围绕保护API Sever来设计的。Kubernetes使用了认证、鉴权,准入控制三步来保证API Server的安全
认证
- HTTP Token认证:通过一个Token来识别合法用户
- HTTP Token的认证是用一个很长的特殊编码方式的并且被难以模仿的字符串-Token来表达客户的一种方式。Token是一个很长的很复杂的字符串,每一个Token对应一个用户名存储在API Server能访问的文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token
- HTTP Base认证:通过用户名+密码的方式认证
- 用户名+:+密码用BASE64算法进行编码后的字符串放在HTTP Request中的Headther Authorization域里发送给服务端,服务端收到后进行编码,获取用户名和密码
- 最严格的HTTPS证书认证:基于CA根证书签名的客户端身份认证方式
需要访问API Sever的组件
- Kubernetes组件对API Server的访问: kubectl,Controller Manager,Scheduler,kubelet,kube-proxy
- Kubernetes管理的Pod对容器的访问:Pod(dashborad也是以Pod形式运行)
安全性说明:
- Controller Manager, Scheduler 与 API Server在同一台机器,所以直接使用API Server的非安全端口访问, --insecure-bind-address=127.0.0.1
- kubectl,kubelet,kube-proxy访问API Server就都需要证书进行HTTPS双向认证
证书颁发:
- 手动签发:通过k8s集群的根ca进行签发HTTPS证书
- 自动签发:kubelet首次访问API Server时,使用token做认证,通过后,Controller Manager会为kubelet生成一个证书,以后的访问都是用证书做认证
kubeconfig
- kubeconfig文件包含集群参数(CA证书、API Server地址),客户端参数(上面生成的证书和私钥),集群context信息(集群名称,用户名)。Kubenetes组件通过启动时指定不同的kubeconfig文件可以切换到不同的集群
- ~/.kube/config 就是config文件
ServiceAccount
- Pod中的容器访问API Server。因为Pod的创建、销毁是动态的,所以要为它手动生成证书就不可行了。kubenetes使用了Service Account解决Pod访问API Server的认证问题
Secret与SA的关系
- Kubernetes设计了一种资源对象叫做Secret,分为两类,一种是用于ServiceAccount的service-account-token,另一种是用于保存用户自定义保密信息的Opaque。ServiceAccount中用到包含三个部分:Token、ca.crt、namespace
- token是使用API Server私钥签名的JWT。用于访问API Server时,Server端认证
- ca.crt,根证书。用于Client端验证API Server发送的证书
- namespace,标识这个service-account-token的作用域名空间
总结:
鉴权
- AlwaysDeny: 拒绝所有的请求
- AlwaysAllow: 允许接收所有请求
- ABAC: 基于属性的访问控制,标识使用用户配置的授权规则对用户进行匹配和控制
- Webbook:通过调用外部REST服务对用户进行授权
- RBAC:基于角色的访问控制
RBAC
- 对集群中的资源和非资源均拥有完整的覆盖
- 整个RBAC完全由几个API对象完成
- 可以再运行时进行调整,无需重启API Server
1.RBAC的API资源对象说明
RBAC引入4个新的顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding,4种对象类型均可以通过kubectl与API操作
需要注意的是kubenetes并不会提供用户管理,由CA申请证书时,提供
{
"CN": "admin",
"host": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "system:masters",
"OU": "System"
}
]
}
# 其中CN为User, names.o为Group
Role and ClusterRole
在RBAC API中,Role表示一组规则权限,权限只会增加,不存在一个资源一开始就有很多权限而通过RBAC对其进行减少的操作,Role可以定义一个namespace中,如果想要跨namespace则可以创建ClusterRole
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
ClusterRole具有与Role相同的权限角色控制能力,不同的是ClusterRole是集群级别的,ClusterRole可以用于:
- 集群级别的资源控制
- 非资源型endpoints
- 所有命名空间资源控制
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get","watch","list"]
RoleBinding and ClusterRoleBinding
RoleBinding 可以将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表,权限列表中包含有不同形式的待授权资源类型;RoleBinding同样包含对被Bind的Role引用;RoleBinding适用于某个命名空间内授权,而ClusterRoleBinding适用于集群范围内的授权
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
RoleBinding同样可以引用ClusterRole来对当前namespace内用户,用户组或ServiceAccount进行授权,这种操作允许集群管理员在整个集群内定义一些通用的ClusterRole,然后在不同的namespace中使用RoleBinding来引用
例如,以下RoleBinding引用了一个ClusterRole,这个ClusterRole具有整个集群内对secrets的访问权限;但是其授权用户dave只能访问development空间中的secrets,因为RoleBinding定义在development命名空间
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets
namespace: development
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
使用ClusterRoleBinding可以对整个集群中的所有命名空间资源权限进行授权;以下ClusterRoleBinding样例展示了授权manager组内所有用户在全部命名空间中对secrets进行访问
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
Resources
kubernetes集群内一些资源一般以其名称字符串来表示,这些字符串一般会在API的URL地址中出现,同时某些资源也会包含子资源,例如logs资源就属于pods的子资源,API中URL样例如下
GET /api/v1/namespaces/{namespace}/pods/{name}/log
如果要在RBAC授权模型中控制这些子资源的访问权限,可以通过/分隔符来实现,以下是一个定义pods资源logs访问权限的Role定义样例
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods","pods/log"]
verbs: ["get","list"]
to subjects
RoleBinding 和ClusterRoleBinding可将Role绑定到Subjects;Subjects可以使groups/users/service accounts
subjects中Users使用字符串表示,它可以是一个普通的名字字符串,如"alice";有也可以是email格式的邮箱;甚至是一组字符串形式的数字id,但是Users的前缀system;是系统保留的,集群管理员应该确保普通用户不会使用这个前缀格式
Groups书写与Users相同,都为一个字符串,并且没有特定的格式要求
实践:创建一个用户只能管理dev空间
{
"CN": "devuser",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "Beijing",
"L": "Beijing",
"O": "k8s",
"OU": "System"
}
]
}
# 下载证书生成工具
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes ~/Desktop/k8s/taint/cert/devuser/devuser-csr.json | cfssljson -bare devuser
# 设置集群参数
export KUBE_APISERVER="https://172.16.21.235:6443"
kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=devuser.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials devuser --client-certificate=/etc/kubernetes/pki/devuser.pem --client-key=/etc/kubernetes/pki/devuser-key.pem --embed-certs=true --kubeconfig=devuser.kubeconfig
# 设置上下文参数
kubectl config set-context kubernetes --cluster=kubernetes --user=devuser --namespace=dev --kubeconfig=devuser.kubeconfig
# 设置默认上下文
kubectl conifg use-context kubernetes --kubeconfig=config
cp -f ./devuser.kubeconfig /root/.kube/config
kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
准入控制
准入控制是API Server的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于API Server的一些主要的功能都需要通过Admission Controllers实现,比如ServiceAccount
官方文档上有一份针对不同版本的准入控制器推荐列表,其中最新的1.14的推荐列表是
- NamespaceLifecycle: 防止在不存在的namespace上创建对象,防止删除系统预置namespace,删除namespace时,连带删除它的所有资源对象
- LimitRanger:确保请求的资源不会超过资源所有Namespace的LimitRange的限制
- ServiceAccount:实现了自动添加的ServiceAccount
- ResourceQuota:确保请求的资源不会超过资源的ResourceQuota限制
部署Helm
Helm本质是让K8s的应用管理可配置,能动态生成,通过动态生成K8s资源清单文件。然后调用Kubectl自动执行K8s资源部署
Helm是官方提供的类似于YUM的包管理器,是部署环境的流程封装
- chart是创建一个应用的信息集合,包括各种Kubernetes对象的配置模板,参数定义,依赖关系,文档说明等。chart是应用部署的自包含逻辑单元。可以将chart想象成apt、yum中的软件安装包
- release是chart的运行实例,代表了一个正在运行的应用。当chart被安装到Kubernetes集群,就生成一个release。chart能够多次安装到同一个集群。每次安装都是一个release
Helm包含两个组件:Helm客户端和Tiller服务器
Helm客户端负责chart和release的创建和管理以及和Tiller的交互。Tiller服务器运行在kubernetes集群中,它会处理Helm客户端的请求,与Kubernetes API Server交互
安装
github下载:https://github.com/helm/helm/releases
cd linux-amd64/
cp helm /usr/local/bin/
chmod +x /usr/local/bin/helm
为了安装服务端tiller,还需要在这台机器上配置好kubectl工具和kubeconfig文件,确保kubectl工具可以在这台机器上访问apiserver且正常使用。这里的node1节点以及配置好的kubectl
因为Kubernetes APIServer开启了RBAC访问控制,所以需要创建tiller使用的service account:tiller并分配合适的角色给它。详细内容可以查看Helm文档。这里直接分配cluster-admin这个集群内置的ClusterRole给它。创建rbac-config.yaml文件:
apiVersion: v1
kind: ServiceAccount
metadata:
name: tiller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
kubectl create -f rbac-config.yaml
helm init --service-account tiller --skip-refresh
helm version
Helm自定义模板
./Chart.yaml
name: hello-world
version: 1.0.0
cat << 'EOF' > ./templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
EOF
cat <<'EOF'>./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: hello-world
EOF
helm install . # build当前文件
# 配置提现在配置文件 values.yaml
cat <<'EOF' > ./values.yaml
image:
repository: gcr.io/google-samples/node-hello
tag: '1.0'
EOF
# 这个文件中定义的值,在模板文件中可以通过.Values对象访问到
cat <<'EOF' > ./templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
protocol: TCP
EOF
在values.yaml中的值可以被部署release时用到的参数 --values YAML_FILE_PATH 或 --set key1=value1,key2=value2覆盖掉
helm install --set image.tag='latest'
# 升级版本
helm upgrade halting-umbrellabird .
# 真正删除
helm delete --purge umbrellabird
# 列出已删除
herm list --deleted
# 回滚
helm rollback halting-umbrellabird 1
# 尝试运行
helm install --dry-run .