• K8s如何从私有Harbor中拉取镜像并完成部署


    本章主要将如何将已经提交到Harbor仓库的镜像在k8s体系内完成部署工作。

    简单扫盲

    粗略介绍下k8s的内容体系,便于理解后面配置文件。

    k8s体系简介

    k8s整体可以分几个部分:namespace,configMap,deployment,pod,service,ingress。

    namespace

    命名空间,其实和java中namespace类似,主要是为了对k8s的对象进行区域划分以及资源隔离。

    你可以认为每个namespace下的对象是不能够共享的。并且你可以针对namespace进行配置,设置这个namespace下可以使用的服务器资源的配额。例如cpu核心,存储,网络等等。

    这里不再详述。

    namespace简写ns

    configMap

    k8s的配置对象,可以绑定到k8s对象上面,让对象能够读取configMap中的配置信息,主要是key:value信息。当然是否要使用,需要自行判断。同时需要程序端配合。不然你运营配置了,程序没加载,依然没用。

    deployment&pod

    这俩需要一块说明一下。

    K8s中的pod,你可以理解为docker中的容器。k8s中创建一个pod,就等于docker run创建了一个容器。也就是说pod是镜像的实例,是实际运行jar包或者nginx的对象。

    pod实际上是可以单独创建的。

    kubectl create pod命令就可以创建一个pod容器。当然用kubectl apply一个yaml文件效果一样。

    但是单独创建的pod有一些问题。

    1. pod作为容器,是会动态分配ip的,动态分配的ip不可控。

    2. pod被删除后,或者pod由于程序问题死掉了,是不会自动恢复的。也就是说,你直接创建的pod,如果执行了kubectl delete pod,那么pod就真的被删除掉了。不会享受到k8s的高可用。

    这么玩费劲搞k8s有啥用?所以我们一般不会直接创建pod,而是将创建pod和pod管理这个事情托管给deployment。

    deployment可以理解为一组管理策略。我们创建一个deployment,然后在里面指定我要启用几个pod,pod用什么镜像,需要配置什么env环境变量等等信息。

    然后通过kubectl create deployment或者kubectl apply -f deployment.yaml创建deployment对象。那么k8s会根据deployment对象的配置,自行创建需要的pod。并且pod和deployement存在关联关系。

    例如我deploy中定义要创建2个pod,那么系统中就会自动创建两个pod。这时你如果删除一个,那么系统会自动再重新创建一个pod,补足2个pod配置要求。同样的,pod死掉,系统也会自动补足2个,确保k8s平台有2个活着的pod。这是k8s高可用的一个前提。

    deployment简写deploy

    service

    deploy虽然可以解决pod管理问题,但是依然无法解决pod动态ip的问题(这是由于框架需要决定的,毕竟pod随时可以扩展,并且随时会被替换,不适合制定固定ip)。于是我系统如何被请求到就出现一个问题。

    k8s设计了service解决该问题。

    service一旦被创建,那么ip变会被固定下来,并且service不是一容器形式存在,所以也不牵扯死掉重新创建等问题。所以k8s中,通过service将pod中的服务提供出来。

    service一般是绑定到deploy上面,通过配置targetPort将deploy下pod的服务端口开放出来。并且service还具备负载均衡能力。如果deploy下配置了多个pod,那么service会根据负载均衡策略对pod进行轮训转发。这样就解决了pod动态ip,并且deploy下的pod可能会随时被替换的问题。

    serivce简写svc

    ingress

    k8s的一个路由组件。

    k8s提供的网络访问方式有3中,ClusterIP,NodePort,LoadBalancer。

    ClusterIP方式,只能够在k8s集群内部服务器间通讯。

    NodePort方式,可以将node上的pod或者service的业务端口映射到主节点上,从而可以通过主节点ip:映射端口方式,对集群外终端提供请求服务。

    LoadBanlancer需要配合前端负载均衡服务或者设备使用,这里不提。

    ClusterIP,显然无法满足外部请求需要;NodePort,小规模K8s的话可以使用,他最多可以使用1w左右节点,默认从3w以后开始分配。

    为了满足大规模k8s集群应用,ingress诞生了。

    ingress有几种,一般多用nginx实现版本。

    他会在k8s集群中的每个worknode上创建一个示例pod,对改节点上的service和pod进行访问代理。

    同时他可以定义一个全局的ingress服务,对每个node上的ingresscontroller进行管理。

    同时,ingress可以提供域名和路由的配置,这样就是先了外部请求进入ingress,ingress根据配置进行匹配,匹配到响应服务后,转发到对应节点的对应服务上,从而完成服务对外提供。就解决了端口问题。

    例如:

    www.abc.cn->svc1

    www.def.cn->svc2

    k8s部署

    k8s部署说白了就是从harbor拉取镜像,创建容器,然后配置网络,实现外部对容器的请求。

    整体用到的内容,就是上面扫盲的内容。

    具体实现的办法,是通过yaml,完成上面内容的配置,然后通过kubectl apply -f xxx.yaml完成相关对象的创建。

    后端部署模板

    模板代码

    1. apiVersion: v1
    2. kind: Namespace
    3. metadata:
    4. name: mysql
    5. #对应部署的命名空间
    6. ---
    7. apiVersion: v1
    8. kind: ConfigMap
    9. #类型为configmap
    10. metadata:
    11. name: uaa
    12. namespace: mysql
    13. #对应部署的命名空间
    14. data:
    15. application.yml: ''
    16. ---
    17. apiVersion: apps/v1
    18. kind: Deployment
    19. #类型为deployment,deployment主要管理无状态应用
    20. metadata:
    21. labels:
    22. app: uaa
    23. name: uaa #应用名称
    24. namespace: mysql #所属命名空间
    25. spec:
    26. replicas: 1 # 配置创建pod实例数量
    27. selector: # k8s中对象的关联关系就是通过对对象打label和selector实现的绑定 所有符合selector的对象都是改对象的关联对象
    28. matchLabels: &id001 # yaml中锚点,类似变量
    29. app: uaa
    30. app-pod: uaa
    31. template:
    32. metadata:
    33. annotations:
    34. serialNumber: '20220523094344'
    35. labels: *id001 # 引用上面定义的锚点 变量的值
    36. namespace: mysql
    37. spec:
    38. containers:
    39. - args: []
    40. env:
    41. - name: RUNTIME
    42. value: docker
    43. - name: RUNTIME_ENV
    44. value: prd
    45. - name: RUNTIME_MYSQL_PASSWORD #数据库密码
    46. value: '123456'
    47. - name: spring.redis.host #redis ip
    48. value: 192.168.216.219
    49. image: shandong.harbor.cn:55443/test/uaa:1.3.39 #镜像版本
    50. imagePullPolicy: Always #镜像拉取策略
    51. name: test-uaa
    52. ports:
    53. - containerPort: 8080
    54. readinessProbe:
    55. initialDelaySeconds: 5
    56. periodSeconds: 3
    57. tcpSocket:
    58. port: 8080
    59. resources:
    60. limits: #资源限制
    61. cpu: '8'
    62. memory: 2G
    63. requests:
    64. cpu: 100m
    65. memory: 500m
    66. volumeMounts:
    67. - mountPath: /var/log/andevopslog
    68. name: logpath
    69. imagePullSecrets:
    70. - name: images-registry #定义镜像拉取的密钥 需要按照harbor账号密码进行配置
    71. initContainers: #初始化容器,初始化如果要执行sql,打镜像的时候写在初始化容器里,先于主容器执行
    72. - command:
    73. - sh
    74. - -c
    75. - mysql -h$RUNTIME_MYSQL_HOST -P$RUNTIME_MYSQL_PORT -u$RUNTIME_MYSQL_USER
    76. -p$RUNTIME_MYSQL_PASSWORD < /opt/app/upgrade_sql/update.sql
    77. env: #环境变量同上
    78. - name: RUNTIME_MYSQL_PASSWORD
    79. value: '123456'
    80. - name: SQL_EXECUTE_MODE
    81. value: upgrade
    82. - name: server.port
    83. value: '8080'
    84. name: init-uaa-sql-execute-job
    85. restartPolicy: Always
    86. volumes:
    87. - emptyDir: {}
    88. name: logpath
    89. ---
    90. apiVersion: v1
    91. kind: Service #定义服务名,k8s内部访问的端口
    92. metadata:
    93. labels: &id001
    94. app-pod: uaa
    95. name: uaa
    96. namespace: mysql
    97. spec:
    98. ports:
    99. - name: http-80
    100. port: 80 #k8s集群内部服务之间访问service的入口
    101. targetPort: 8080 #容器的端口
    102. selector: *id001
    103. ---
    104. apiVersion: extensions/v1beta1
    105. kind: Ingress #定义对外暴露使用的方式为ingress
    106. metadata:
    107. annotations:
    108. nginx.ingress.kubernetes.io/rewrite-target: /$2
    109. labels:
    110. app: uaa
    111. name: uaa
    112. namespace: mysql
    113. spec:
    114. rules:
    115. - host: demo.test.com.cn #对外暴露使用的域名
    116. http:
    117. paths:
    118. - backend:
    119. serviceName: uaa #对外暴露指向内部的服务名service
    120. servicePort: 80
    121. path: /test/uaa(/|$)(.*) #路由地址
    122. ---

    上面模板包含了一个后台应用上线需要配置的所有相关对象。

    这里要说明的是,env下配置的环境变量,需要和研发配合才能生效,否则就算容器配置了该变量,也不一定起作用,后面会单独讲解。

    使用的时候,根据需要,修改namespace,各个对象的name,镜像信息,env信息,端口,ingress的域名和路由即可。

    前端部署模板

    模板代码

    1. apiVersion: v1
    2. kind: Namespace
    3. metadata:
    4. name: mysql #定义部署的命名空间
    5. ---
    6. apiVersion: v1
    7. kind: ConfigMap #定义类型为configmap,configmap主要是一些配置,下发是nginx的配置
    8. metadata:
    9. name: coreweb
    10. namespace: mysql
    11. data:
    12. nginx.conf: |
    13. #user nobody;
    14. worker_processes 1;
    15. #error_log logs/error.log;
    16. #error_log logs/error.log notice;
    17. #error_log logs/error.log info;
    18. #pid logs/nginx.pid;
    19. events {
    20. worker_connections 1024;
    21. }
    22. http {
    23. include mime.types;
    24. default_type application/octet-stream;
    25. #log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    26. # '$status $body_bytes_sent "$http_referer" '
    27. # '"$http_user_agent" "$http_x_forwarded_for"';
    28. #access_log logs/access.log main;
    29. sendfile on;
    30. tcp_nopush on;
    31. client_max_body_size 500m;
    32. #keepalive_timeout 0;
    33. keepalive_timeout 200;
    34. gzip on;
    35. gzip_vary on;
    36. gzip_min_length 1k;
    37. gzip_comp_level 4;
    38. gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/javascript;
    39. gzip_disable "MSIE [1-6]\.";
    40. add_header X-Frame-Options DENY;
    41. server {
    42. listen 8080; #端口
    43. server_name localhost;
    44. location ^~ / {
    45. #root html;
    46. alias /usr/share/nginx/html/; #这里路径要和dockerfile中copy的前端文件路径一致
    47. index index.html index.htm;
    48. try_files $uri $uri/ /index.html;
    49. client_max_body_size 500m;
    50. }
    51. error_page 500 502 503 504 /50x.html;
    52. location = /50x.html {
    53. root html;
    54. }
    55. }
    56. }
    57. ---
    58. apiVersion: apps/v1
    59. kind: Deployment #类型为deployment,deployment主要管理无状态应用
    60. metadata:
    61. labels:
    62. app: coreweb
    63. name: coreweb
    64. namespace: mysql
    65. spec:
    66. replicas: 1
    67. selector:
    68. matchLabels: &id001
    69. app: coreweb
    70. app-pod: coreweb
    71. template:
    72. metadata:
    73. annotations:
    74. serialNumber: '20220523124824'
    75. labels: *id001
    76. namespace: mysql
    77. spec:
    78. containers: #定义容器内的环境变量,前端不会请求这些变量,可有可无
    79. - args: []
    80. env:
    81. - name: RUNTIME
    82. value: docker
    83. - name: RUNTIME_ENV
    84. value: prd
    85. image: shandong.harbor.cn:55443/test/coreweb:1.3.229 #镜像版本
    86. imagePullPolicy: Always #镜像拉取策略
    87. name: onepark-coreweb
    88. ports:
    89. - containerPort: 8080
    90. readinessProbe:
    91. initialDelaySeconds: 5
    92. periodSeconds: 3
    93. tcpSocket:
    94. port: 8080
    95. resources:
    96. limits:
    97. cpu: '8'
    98. memory: 2G
    99. requests:
    100. cpu: 100m
    101. memory: 500m
    102. volumeMounts:
    103. - mountPath: /var/log/andevopslog #容器日志路径
    104. name: logpath
    105. - mountPath: /etc/nginx/nginx.conf #将configmap挂载进去
    106. name: config
    107. subPath: nginx.conf
    108. imagePullSecrets:
    109. - name: image-secret #定义镜像拉取的密钥
    110. restartPolicy: Always
    111. volumes:
    112. - emptyDir: {} #emptyDir类型的volume在pod分配到node上时被创建,kubernetes会在node上自动分配 一个目录,因此无需指定宿主机node上对应的目录文件。这个目录的初始内容为空,当Pod从node上移除时,emptyDir中的数据会被永久删除。
    113. name: logpath
    114. - configMap:
    115. name: coreweb
    116. name: config
    117. ---
    118. apiVersion: v1
    119. kind: Service #定义服务名,k8s内部访问的端口
    120. metadata:
    121. labels: &id001
    122. app-pod: coreweb
    123. name: coreweb
    124. namespace: mysql
    125. spec:
    126. ports:
    127. - name: http-80
    128. port: 80 #k8s集群内部服务之间访问service的入口
    129. targetPort: 8080 #容器的端口
    130. selector: *id001
    131. ---
    132. apiVersion: extensions/v1beta1
    133. kind: Ingress #定义对外暴露使用的方式为ingress
    134. metadata:
    135. annotations:
    136. nginx.ingress.kubernetes.io/rewrite-target: /$2
    137. labels:
    138. app: coreweb
    139. name: coreweb
    140. namespace: mysql
    141. spec:
    142. rules:
    143. - host: web.demo.cn #定义访问的域名
    144. http:
    145. paths:
    146. - backend:
    147. serviceName: test #对外暴露指向内部的服务名service
    148. servicePort: 80
    149. path: /()(.*)
    150. ---

    前端就相对简单了,主要是nginx的配置要对起来。

    下面给一个示例图片

     

    PS:

            首先你要先确保你的k8s环境和网络没问题!!!

  • 相关阅读:
    你知道网关 架构是如何演进?
    学习笔记16--汽车运动控制理论之经典控制理论
    C#中的四种类型转换
    Nuclei(二)进阶——深入理解workflows、Matchers和Extractors
    华为云CDN,为金融行业使用户打造优质网络使用环境
    广电5G正式启航,黄金频段将如何应用引关注
    这份Java面试八股文堪称2022最强,让329人成功进入大厂
    记录一次紧急的版本切换
    校园论坛系统设计
    计算摄影——图像去噪(一)
  • 原文地址:https://blog.csdn.net/lanwilliam/article/details/125906633