阿里云ack的创建与应用案例
- 创建前开通ack相关服务:
- 开始创建
- 简单的魔方游戏,熟悉sv与clb自动注册创建
- 部署一个nginx 服务示例:
- 走不同域名访问不同svc资源:
- 为什么需要 Ingress ?
- 创建第一个域名的 Deployment和Service。
- 创建第二个域名的 Deployment和Service。
- 部署Ingress
- 测试访问情况
- 灰度发布与蓝绿发布参考:
- 探针场景
- 为什么要用探针?
- **探针案例**
- 生命周期举例
- ack云日志如何接入(阿里的Logtail产品)
创建前开通ack相关服务:
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/getting-started/quick-start-for-first-time-users/?spm=a2c4g.11186623.help-menu-85222.d_1_1.1b1c15442gwzA8&scm=20140722.H_161387._.OR_help-T_cn#DAS#zh-V_1
开始创建
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/create-an-ack-managed-cluster-2?spm=a2c4g.11186623.help-menu-85222.d_2_0_2_0.71e34e25vspFLq&scm=20140722.H_95108._.OR_help-T_cn#DAS#zh-V_1
测试环境:选择使用 EIP 暴露 API Server, 才能在远程连接或者通过控制台的cloudshell管理集群
生产环境:找一台内网安装有kebctl客户端机器进行访问(做好访问权限控制)
连接设置:
复制k8s的外网远程连接配置到conf中
记得先备份好本地的config文件
cd $HOME/.kube/
cp config config.local.back
echo > config
vi config
查看nodes节点情况:
lantai@lantaideMacBook-Pro .kube % kubectl get nodes
NAME STATUS ROLES AGE VERSION
cn-chengdu.10.194.33.154 Ready <none> 54m v1.31.1-aliyun.1
cn-chengdu.10.245.11.206 Ready <none> 54m v1.31.1-aliyun.1
注:没有节点信息就不正常,一般原因是余额不足,导致无法创建节点资源。
简单的魔方游戏,熟悉sv与clb自动注册创建
基于clb注册暴露服务端口,会新创建一个clb进行转发到node的暴露端口上,
不太推荐生产,多创建一个clb就多消耗资源(根据业务规模情况吧)
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/getting-started/getting-started-with-ack-using-kubectl?spm=a2c4g.11186623.help-menu-85222.d_1_3.202c1a00AcmOam&scm=20140722.H_309552._.OR_help-T_cn#DAS#zh-V_1
部署前的clb:
部署后的clb:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ack-cube-svc LoadBalancer 192.168.31.155 47.108.xx.xx 80:31547/TCP 32s
在浏览器地址栏输入该服务EXTERNAL-IP字段的IP地址,即可开始魔方游戏。
删除练习相关资源:
kubectl delete -f ack-cube-svc.yaml
kubectl delete -f ack-cube.yaml
slb中的资源会自己删除:
部署一个nginx 服务示例:
基于clb注册暴露服务端口
- 先配置deployment
apiVersion: apps/v1 # for versions before 1.8.0 use apps/v1beta1
kind: Deployment
metadata:name: nginx-test #应用名称。labels:app: nginx-test
spec:replicas: 1 #设置副本数量。selector:matchLabels:app: nginx-test #对应服务中Selector的值需要与其一致,才可以通过服务公开此应用。template:metadata:labels:app: nginx-testspec:containers:- name: nginx-testimage: anolis-registry.cn-zhangjiakou.cr.aliyuncs.com/openanolis/nginx:1.14.1-8.6 #替换为您实际的镜像地址,格式为:<image_name:tags>。ports:- containerPort: 80 #需要在服务中暴露该端口。
Deployment资源创建与验证:
kubectl apply -f nginx-test.yaml
kubectl get deployment nginx-test
- 配置nginx的 sv
apiVersion: v1
kind: Service
metadata:labels:app: nginx-testname: nginx-test-svcnamespace: default
spec:ports:- port: 8080 #公网暴露的端口,用了clb下面是LoadBalancer会自动开放端口到eip中protocol: TCPtargetPort: 80 selector:app: nginx-test # 需要与Deployment YAML文件中的matchLabels的值一致。type: LoadBalancer # 使用clb自动注册,需要配置为LoadBalancer类型
Service资源创建与验证:
kubectl apply -f nginx-svc.yaml
kubectl get svc nginx-test-svc
lantai@lantaideMacBook-Pro .kube % kubectl get svc nginx-test-svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-test-svc LoadBalancer 192.168.31.180 47.108.*.* 8080:30456/TCP 18m
浏览器中访问: EXTERNAL-IP:8080
EXTERNAL-IP : 外部可访问的公网ip地址
删除资源:
kubectl delete -f nginx-svc.yaml
kubectl delete -f nginx-test.yaml
走不同域名访问不同svc资源:
为什么需要 Ingress ?
- Service 可以使用 NodePort 暴露集群外访问端口,但是性能低、不安全并且端口的范围有限。
- Service 缺少七层(OSI 网络模型)的统一访问入口,负载均衡能力很低,不能做限流、验证非法用户、链路追踪等等。
- Ingress 公开了从集群外部到集群内
服务
的 HTTP 和 HTTPS 路由,流量路由由 Ingress 资源上定义的规则控制。 - 我们使用 Ingress 作为整个集群统一的入口,配置 Ingress 规则转发到对应的 Service 。
基于ack中的ingress进行域名的转发规则实验:
ack的ingress配置参考:
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/create-an-nginx-ingress-1?spm=a2c4g.11186623.0.0.1b1c4d29tyipum
ack ingress的副本数量控制:
https://help.aliyun.com/zh/ack/deploy-ingresses-in-a-high-reliability-architecture?spm=a2c4g.11186623.0.0.17ffae7bmNEj0W#task-1339886
k8s的ingress参考:
https://kubernetes.io/docs/concepts/services-networking/ingress/
生产环境的svc的type类型建议如下
type: ClusterIP
创建第一个域名的 Deployment和Service。
创建一个old-nginx.yaml 资源清单
apiVersion: apps/v1
kind: Deployment
metadata:name: old-nginx
spec:replicas: 1selector:matchLabels:run: old-nginx # 标签和service资源定义的对应好template:metadata:labels:run: old-nginxspec:containers:- image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx # 用的阿里封装过的镜像,生产根据实际情况配置镜像仓库地址imagePullPolicy: Alwaysname: old-nginxports:- containerPort: 80protocol: TCPrestartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:name: old-nginx
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:run: old-nginxsessionAffinity: Nonetype: NodePort
b. 执行以下命令,创建Deployment和Service。
kubectl apply -f old-nginx.yaml
创建第二个域名的 Deployment和Service。
创建new-nginx.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:name: new-nginx
spec:replicas: 1selector:matchLabels:run: new-nginxtemplate:metadata:labels:run: new-nginxspec:containers:- image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginximagePullPolicy: Alwaysname: new-nginxports:- containerPort: 80protocol: TCPrestartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:name: new-nginx
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:run: new-nginxsessionAffinity: Nonetype: NodePort
b. 执行以下命令,创建Deployment和Service。
kubectl apply -f new-nginx.yaml
部署Ingress
创建ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress-http
spec:rules: # 规则,这里配置的域名规则,类似nginx# 第一个svc域名- host: www.example.comhttp:paths:# 老版本nginx服务。- path: /backend:service: name: old-nginxport:number: 80 # 后端svc的端口号pathType: ImplementationSpecific# 第二个svc域名- host: www.test.comhttp:paths:# 新版本nginx服务。- path: /backend: # 指定路由到后端服务的service 相关配置service: name: new-nginxport:number: 80 # 后端svc的端口号pathType: ImplementationSpecific # ImplementationSpecific 匹配方法取决于 IngressClass
执行以下命令,部署Ingress。
kubectl apply -f ingress.yaml
测试访问情况
查看ingress, 获取外部访问IP:
lantai@lantaideMacBook-Pro .kube % kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-http nginx www.example.com,www.test.com 47.108.*.184 80 18s
查看clb控制面板并没有增加条目,因为这次不是LoadBalancer类型的svc, 是NodePort类型的svc,不会向clb注册条目,这次依靠ack内部的ingress组件进行域名转发:
本地电脑主机编辑/etc/hosts进行测试:
47.108.*.184 www.test.com
47.108.*.184 www.example.com
然后,通过浏览器访问不同的域名进行测试,测试效果如下:
测试完清空资源:
kubectl delete -f ingress.yaml
kubectl delete -f old-nginx.yaml
kubectl delete -f new-nginx.yaml
灰度发布与蓝绿发布参考:
https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/implement-gray-scale-and-blue-green-publishing-through-nginx-ingress?spm=a2c4g.11186623.help-menu-85222.d_2_3_5_2_7.7d9fae7beFROdE&scm=20140722.H_200941._.OR_help-T_cn~zh-V_1#38348104fea19
可基于请求头、cookie 、请求参数,流量权重等控制。
探针场景
为什么要用探针?
主要做 健康检查
- 在 Kubernetes 中,探针不是默认配置的,需要手动添加到 Pod 的定义中。
- 如果没有添加
livenessProbe
和readinessProbe
,Kubernetes 不会自动进行基于应用层协议(如 HTTP)的健康检查,只会检查容器是否成功启动(即容器的主进程是否运行)。
- 如果没有添加
-
容器启动状态检查
- 默认情况下,Kubernetes主要关注容器是否成功启动并进入
Running
状态。当Kubernetes调度一个Pod到节点上后,它会等待容器的主进程启动。如果主进程能够正常启动,容器就会被标记为Running
。
- 默认情况下,Kubernetes主要关注容器是否成功启动并进入
-
容器运行后的健康监测缺失(默认情况)
- 然而,仅容器启动成功并不意味着应用在整个生命周期内都能正常提供服务。例如,应用可能会出现死锁、进入无限循环、耗尽资源等情况,导致虽然容器仍在运行,但服务已经不可用。默认情况下,Kubernetes没有内置对这些应用层问题的检查机制,这就需要通过手动添加探针(如
livenessProbe
和readinessProbe
)来实现更细致的健康监测。
- 然而,仅容器启动成功并不意味着应用在整个生命周期内都能正常提供服务。例如,应用可能会出现死锁、进入无限循环、耗尽资源等情况,导致虽然容器仍在运行,但服务已经不可用。默认情况下,Kubernetes没有内置对这些应用层问题的检查机制,这就需要通过手动添加探针(如
-
与Pod生命周期的关系
- 在Pod的生命周期管理中,默认的
Running
状态判断相对比较基础。从创建Pending
到进入Running
,Kubernetes确保了容器能够启动,但对于后续可能出现的各种应用故障场景,没有默认的主动监测。添加探针后,可以更好地管理Pod在Running
状态下的健康状况,例如通过livenessProbe
来决定是否重启故障容器,通过readinessProbe
来确定容器是否可以接收流量,这些操作有助于维护应用的高可用性和稳定性。
- 在Pod的生命周期管理中,默认的
-
Pod生命周期概述
- 创建阶段(
Pending
):当创建一个Pod时,它首先进入Pending
状态。此时,Kubernetes正在为Pod分配节点资源,包括下载镜像等操作。例如,若Pod请求的资源(如CPU、内存)在集群中暂时无法满足,或者镜像拉取出现问题,Pod就会一直处于Pending
状态。 - 运行阶段(
Running
):当Pod成功被调度到节点并且容器启动后,进入Running
状态。此时,容器内的应用程序开始运行,提供相应的服务。但这并不意味着应用完全健康,可能还需要进一步的健康检查(通过探针)来确保服务的质量。 - 终止阶段(
Succeeded
或Failed
):当容器内的主进程正常退出时,Pod状态变为Succeeded
;如果容器内主进程异常退出或者容器无法启动,Pod状态变为Failed
。
- 创建阶段(
-
kubernetes提供了两种探针来实现容器探测,分别是:
- 存活探针(
livenessProbe
):- 用于判断容器是否还在“存活”状态。
- 如果存活探针检测失败,Kubernetes会根据配置的策略(如重启容器)来尝试恢复服务。
-
- 例如,对于一个Web应用,可以设置一个HTTP存活探针,定期发送HTTP请求到应用的某个端点,如果连续多次无法得到正确响应(如返回状态码不是
200-299
),就认为容器可能出现问题,需要重启。 - 在 Kubernetes 中,当
livenessProbe
(存活探针)检测失败达到一定次数(failureThreshold
)时,默认行为是重启容器。- 对于
httpGet
类型的存活探针,Kubernetes 会按照periodSeconds
设置的时间间隔(这里是 5 秒)来检查容器内应用的健康状况。如果连续多次检查(默认failureThreshold
为 3 次)都无法通过(例如,返回的 HTTP 状态码不是 200 - 399 范围内),Kubernetes 就会判定容器不健康,并采取重启操作,以尝试恢复应用的正常运行。
- 对于
- kubernetes就会对容器所在的Pod进行重启,其实这是由Pod的重启策略决定的,Pod的重启策略有3种,分别如下:
- Always:容器失效时,自动重启该容器,默认值。
- OnFailure:容器终止运行且退出码不为0时重启。
- Never:不论状态如何,都不重启该容器。
- 例如,对于一个Web应用,可以设置一个HTTP存活探针,定期发送HTTP请求到应用的某个端点,如果连续多次无法得到正确响应(如返回状态码不是
- 存活探针(
restartPolicy: Never # 重启策略设置格式
-
- 就绪探针(
readinessProbe
):- 用于判断容器是否已经“准备好”接收流量。
- 只有当就绪探针检测成功时,Service才会将流量转发到该容器对应的Pod。
- 例如,一个应用可能在启动后需要一些时间来加载配置文件或者初始化数据库连接,在这个过程中,虽然容器已经运行(存活),但还没有准备好接收流量。通过就绪探针可以确保只有在应用真正准备好后,才会让流量进入。
- 就绪探针(
探针案例
- 将带有探针的Pod纳入Service管理
- 在Pod配置中添加探针(以
Deployment
为例):
假设要部署一个nginx
应用的Pod,并且添加探针。 - 创建一个
Deployment
的YAML
文件如下:
- 在Pod配置中添加探针(以
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment-with-probes
spec:replicas: 3selector:matchLabels:app: nginx-probestemplate:metadata:labels:app: nginx-probesspec:containers:- name: nginx-container-with-probesimage: nginx:latestports:- containerPort: 80livenessProbe:httpGet: # 表示通过发送 HTTP GET 请求的方式来检测容器内应用的状态path: /port: 80initialDelaySeconds: 15 # 在容器启动后,延迟多少秒才开始第一次进行存活探针检测periodSeconds: 5 #它定义了每隔多长时间进行一次存活探针检测,这里设置为 5 秒readinessProbe:httpGet:path: /port: 80initialDelaySeconds: 10 #表示容器启动后,延迟 10 秒才开始第一次进行就绪探针检测periodSeconds: 3
注:在这个配置中,livenessProbe和readinessProbe都是基于httpGet(还有其它方式)方式,即发送HTTP请求来检查容器的状态。path: /表示发送请求到容器内应用的根路径(对于nginx来说就是首页),port: 80表示通过80端口发送请求。initialDelaySeconds是容器启动后延迟多久开始第一次探测,periodSeconds是每次探测的间隔时间。
创建Service
来管理带有探针的Pod:
apiVersion: v1
kind: Service
metadata:name: nginx-service-for-probes
spec:selector:app: nginx-probesports:- port: 80targetPort: 80type: ClusterIP
- 当Pod配置好探针后,创建
Service
来管理这些Pod。例如: - 在
Service
的spec
部分,selector
字段通过app: nginx-probes
来选择带有这个标签的Pod,这些Pod正是之前在Deployment
中配置了探针的nginx
Pod。 ports
部分定义了Service
本身的端口(port: 80
)和转发到Pod的目标端口(targetPort: 80
)。- 这样,
Service
就会根据Pod
的就绪状态(通过就绪探针来判断)将外部流量转发到合适的Pod
上。当Pod
的存活探针检测到容器出现问题时,Kubernetes会按照配置(如重启容器)来处理,而Service
会自动更新其流量转发的目标Pod
列表,确保流量始终导向健康的Pod
。
生命周期举例
lifecycle
配置可以添加到Deployment
中- 在Kubernetes的
Deployment
资源中,可以为容器定义生命周期钩子(lifecycle hooks
),用于在容器启动后(postStart
)和容器停止前(preStop
)执行特定的操作。 - 这对于需要在容器生命周期的关键阶段进行自定义操作(如初始化配置、清理资源等)非常有用。
- 在Kubernetes的
- 示例
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment-with-lifecyclelabels:app: nginx
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:latestlifecycle:postStart: # 启动后exec:command: ["/bin/sh","-c","echo postStart... > /usr/share/nginx/html/index.html"]preStop: # 停止前exec:command: ["/usr/sbin/nginx","-s","quit"]
- 以下是一个包含
lifecycle
配置的Deployment
示例,用于部署一个简单的Nginx应用:
- 在这个示例中:- apiVersion、kind和metadata部分:
apiVersion
指定了使用的Kubernetes API版本(apps/v1
用于Deployment
资源)。kind
定义资源类型为Deployment
。metadata
包含了Deployment
的名称(nginx-deployment-with-lifecycle
)和标签(app: nginx
),用于标识和组织资源。
spec
部分:replicas
字段设置为1
,表示希望运行的Pod副本数量为1个。selector
定义了如何选择这个Deployment
管理的Pod,通过匹配标签app: nginx
来确定。template
部分定义了Pod的模板。metadata
中的标签(app: nginx
)用于Pod的识别。spec
中的containers
字段定义了容器相关信息。- 容器名称为
nginx
,使用nginx:latest
镜像。 lifecycle
配置包含了postStart
和preStop
钩子。postStart
钩子在容器创建后执行,通过exec
方式运行一条命令,将postStart...
写入Nginx容器的/usr/share/nginx/html/index.html
文件,从而修改了Nginx的首页内容。preStop
钩子在容器停止前执行,通过exec
方式运行命令/usr/sbin/nginx - s quit
来优雅地停止Nginx服务,确保在容器完全停止之前,Nginx能够正常关闭,避免数据丢失或服务异常。
- 容器名称为
- apiVersion、kind和metadata部分:
- 应用和验证
kubectl apply -f nginx-deployment-with-lifecycle.yaml
- 可以使用
kubectl
命令来应用这个Deployment
配置: - 之后,可以通过以下方式验证
lifecycle
钩子的执行情况:- 验证
postStart
:- 可以通过访问Nginx服务(如果已经配置了服务暴露),查看Nginx的首页内容是否被修改为
postStart...
。- 例如,如果使用
NodePort
服务类型暴露Nginx服务,可以通过http://<node-ip>:<node-port>
访问,查看返回的页面内容。
- 例如,如果使用
- 可以通过访问Nginx服务(如果已经配置了服务暴露),查看Nginx的首页内容是否被修改为
- 验证
preStop
:- 可以通过手动删除
Deployment
kubectl delete deployment nginx-deployment-with-lifecycle
)- 然后查看容器日志
- (
kubectl logs <pod-name>
)来确认preStop
命令是否被执行。 - 在日志中,应该可以看到Nginx服务被优雅地停止的相关信息。
- (
- 可以通过手动删除
- 验证
ack云日志如何接入(阿里的Logtail产品)
配置参考:https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/collect-log-data-from-containers-by-using-log-service?spm=a2c4g.11186623.help-menu-85222.d_2_9_1_1.341a455bvxC9TP