将你的应用部署在 K8S 上
2020/2/22 17:03:04
本文主要是介绍将你的应用部署在 K8S 上,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Kubernetes(简称 K8S)自发布以来,已经成为容器化编排的最佳工具,本文通过一个简单的案例聊一聊如何将一个容器部署到 k8s 集群上,文中所需的代码和容器均在 GITHUB 上。如需要搭建一个 k8s 集群,可以通过 minikube 来搭建,也可以使用 docker for desktop 自带的 k8s 集群
1 创建一个最简单的 Deployment
先简单介绍几个概念
- Pod: k8s 最核心的一个概念,是一个或多个 container 的集合。一个 pod 中的 container 共享存储和网络,k8s 支持多种 contianer,但是目前 docker container 是最常见的一种。我们的应用最终都是各个 pod 的形式存在的,pod 也是 k8s 进行调度的最小单位。
- ReplicaSet: 也是 k8s 中的一种资源,管理一个 pod 的多个副本。一般我们部署 pod 为了保证高可用,都会部署多个副本,避免单点故障。如果 replicaSet 管理的某个 pod 挂掉了,它会请求一个新的 pod 出来以满足设定的副本数量。k8s 还有一个 ReplicaionController 也是控制 pod 副本的,但是相比 ReplicaionController,ReplicaSet 对 pod 标签的支持会更好,现在一般就用 ReplicaSet
- Deployment: 是一个更 high-level 的资源,创建一个 Deployment 后会创建一个 ReplicaSet,然后 ReplicaSet 会创建预期数量的 pod。deployment 可以对 ReplicaSet 的版本进行管理,方便回滚。在生产上一般都是创建一个 Deployment
我们先准备一个简单的 web 应用 simple-web,并将其打包成 docker 镜像 simple-web:1.0。web 应用后,访问 /index
,将会输出 web 应用的名字,访问 /health
,会返回 "OK"
> curl http://ip:8080/index web site name is [demo-web] > curl http://ip:8080/health OK 复制代码
定义一个 deployment.yml
如下
kubectl create -f deployment.yml
,然后 get 资源可以发现我们创建了一个 deployment,一个 replicaset,一个 pod
➜ ~ k get deploy NAME READY UP-TO-DATE AVAILABLE AGE simple-web 1/1 1 1 2d4h ➜ ~ k get rs NAME DESIRED CURRENT READY AGE simple-web-6bdf7b4d84 1 1 1 47h ➜ ~ k get pods NAME READY STATUS RESTARTS AGE simple-web-6bdf7b4d84-p7jkp 1/1 Running 0 47h 复制代码
我们可以进入到 pod 中执行 curl 命令查看输出,也可以把 curl 命令传递给 kubectl exec
➜ ~ k exec simple-web-6bdf7b4d84-p7jkp -- curl -s http://localhost:8080/index web site name is [demo-web] 复制代码
2 使用 service 访问 pod
2.1 port-forward
仅仅是创建一个 Deployment,我们还只能在 pod 内访问自己的 web 服务,而无法在外部或者 pod 之间访问 web 服务。kubectl port-forward <podname> <hostPort:containerPort>
可以将宿主机的一个 port 代理到容器的一个 pod 上,使我们在宿主机上访问 web 服务
➜ ~ k port-forward simple-web-6bdf7b4d84-p7jkp 8889:8080 Forwarding from 127.0.0.1:8889 -> 8080 Forwarding from [::1]:8889 -> 8080 ➜ ~ curl 127.0.0.1:8889/index web site name is [demo-web] 复制代码
2.2 service
但是当我们有多个副本的 pod 时,我们不可能一个一个 pod 的代理指定端口,同时 port-forward 也没解决 pod 之间的服务发现。这个时候我们需要 Service
来提供路由
创建一个
Service`
apiVersion: v1 kind: Service metadata: name: simple-web spec: selector: app: simple-web ports: - protocol: TCP port: 80 targetPort: 8080 复制代码
这里 selector 我们需要填写在 deployment 中定义的 pod 的标签
➜ ~ k get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE simple-web ClusterIP 10.96.156.194 <none> 80/TCP 2d4h 复制代码
我们创建了一个叫 simple-web
的 service,可以看到 k8s 分配了一个 clusterIP,并将这个 ip 的 80 端口映射到 pod 的 8080 端口
➜ ~ curl 10.96.156.194/index web site name is [demo-web] 复制代码
除了用 ip 访问,我们也可以用 serivce 来访问
➜ ~ k exec simple-web-6bdf7b4d84-2kzxx -- curl http://simple-web/index web site name is [demo-web] 复制代码
2.3 nodeport
使用 ClusterIP 我们只能在 k8s 集群内访问 pod,如果要从外部访问 pod,则可以定义 NodePort type 的 Service
apiVersion: v1 kind: Service metadata: name: simple-web spec: type: NodePort selector: app: simple-web ports: - protocol: TCP port: 80 targetPort: 8080 nodePort: 32100 复制代码
这样我们就可以通过宿主机 ip:nodeport 访问 pod 中的 web 服务了 Service 还提供了 LoadBalancer 的 type,方便提供一个 external 的 ip 供访问,一般为云厂商使用,此处不表
3 Volume
Volume 提供了一种在 pod 的 container 之间数据交互,container 与宿主机或者其它的存储交互的手段。k8s 的 Volume 有很多类型,下面以 EmptyDir 为例看看 Volume 的使用。 我们将 web 应用的 log 挂载到 EmptyDir,配置如下
apiVersion: apps/v1 kind: Deployment metadata: name: simple-web spec: replicas: 1 selector: matchLabels: app: simple-web template: metadata: labels: app: simple-web spec: containers: - name: simple-web image: simple-web:1.0 volumeMounts: - name: app-log mountPath: /app/logs volumes: - name: app-log emptyDir: {} 复制代码
我们可以在宿主机上找到 emptyDir 的路径,默认是 /var/lib/kubelet/pods/PODUID/volumes/kubernetes.io~empty-dir/VOLUMENAME
➜ ~ k get pods simple-web-6bdf7b4d84-2kzxx -o yaml | grep uid uid: 437573bc-7398-4004-89ac-0d268e986c74 uid: be609483-ed6d-427f-b277-81931cc9eb60 复制代码
be609483-ed6d-427f-b277-81931cc9eb60
就是 pod uid
以这个 log 为例,我们宿主机上的 log 可以通过 filebeat 收集起来
4 configmap
当我们把应用部署到 pod 后,如果希望通过更改配置更改应用的行为,肯定不希望是需要重新打包一个镜像,所以我们需要把配置文件分离出来,configmap 就可以帮助我们完成这个事
apiVersion: v1 kind: ConfigMap metadata: name: simple-web-config data: app-config: |- app.name=web-name-from-config-web 复制代码
然后修改 deployment 如下
apiVersion: apps/v1 kind: Deployment metadata: name: simple-web spec: replicas: 1 selector: matchLabels: app: simple-web template: metadata: labels: app: simple-web spec: containers: - name: simple-web image: simple-web:1.0 volumeMounts: - name: app-log-vol mountPath: /app/logs - name: config-vol mountPath: /app/conf/application.properties subPath: application.properties volumes: - name: app-log-vol emptyDir: {} - name: config-vol configMap: name: simple-web-config items: - key: app-config path: application.properties 复制代码
我们把 configmap 里的配置挂载到了 /app/conf/application.properties
,我们应用的启动脚本会读取这个配置文件 java -jar simple-web.jar --spring.config.location=/app/conf/application.properties
,通过这种方式,我们就将配置文件与应用分离。修改配置文件后,application.properties
就已经被更新了,但是由于 java 应用不会重新加载配置文件,所以需要重启 pod
5 liveness, readiness 与 pod resources
5.1 liveness, readiness
k8s 是如何知道一个 pod 无法提供服务了呢?我们需要定义一个健康检查的 liveness ,k8s 会定期请求这个 liveness,判断服务是否健康。 readiness 类似,通过 readiness 的定义判读 pod 是否已经可以开始提供服务
5.2 resources
k8s 提供了限制 container 所能使用的资源量的方法。resources.requests
定义了需要多少资源,用于 k8s 将 pod 调度到资源充足的节点,resources.limits
则限制了 container 可以使用的资源总量。可参考Kubernetes Container Resource Requirements
apiVersion: apps/v1 kind: Deployment metadata: name: simple-web spec: replicas: 1 selector: matchLabels: app: simple-web template: metadata: labels: app: simple-web spec: containers: - name: simple-web image: simple-web:1.0 livenessProbe: httpGet: path: /health port: 8080 readinessProbe: httpGet: path: /health port: 8080 volumeMounts: - name: app-log-vol mountPath: /app/logs - name: config-vol mountPath: /app/conf/application.properties subPath: application.properties resources: requests: memory: 2048Mi cpu: 2 limits: memory: 2048Mi cpu: 2 volumes: - name: app-log-vol emptyDir: {} - name: config-vol configMap: name: simple-web-config items: - key: app-config path: application.properties 复制代码
6 其它待补充,pause 容器等,dashboard
这篇关于将你的应用部署在 K8S 上的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-08云原生周刊:Kubernetes v1.30 发布 | 2024.4.22
- 2024-05-08云原生周刊:K8s 中的服务和网络 | 2024.4.29
- 2024-03-29kubernetes crashloopbackoff
- 2024-03-13ubuntu install kubernetes
- 2024-03-07k8s coredns containercreating
- 2024-03-04k8s for dummies
- 2024-03-01pulumi kubernetes operator
- 2024-02-06云原生周刊:K8s 1.26 到 1.29 版本的更新 | 2024.1.29
- 2024-01-24K8s集群CoreDNS监控告警最佳实践
- 2024-01-23OpenKruise :Kubernetes背后的托底