🌑

Mocha's Blog

目录
  1. 集群搭建
    1. k3s 的安装
      1. Master节点的配置
      2. Node 节点的配置
  2. 基本概念
    1. Pod
      1. Pod的概念
      2. 声明一个 Pod
    2. Deployment
      1. Deployment的概念
      2. 声明一个 Deployment
    3. Service
      1. Service的概念
      2. Service的定义
    4. Ingress
      1. Ingress的概念
      2. Ingress的声明
    5. Secrets
      1. Secrets 的概念
      2. 配置 HTTPS 访问

从零搭建一个k3s集群

发布时间:2021年11月17日

去年来到开源中国后,除了日常开发外经常会跟 k8s 打交道。因为一开始在公司的 CI/CD 能力还不够时,需要自己本地手动进行 docker 镜像的打包、上传以及部署在 k8s 集群中。

在这一年内,掌握了一些简单的 k8s 指令以及相关概念,但自己并没有深入的去了解这块的知识。

上周,公司里的前端同事进行了 k8s 相关基础知识的分享,第一次深入的了解了 pod/service/deployment 的概念,引起了我极大的兴趣,想着把手头上空闲的两台云主机组一个集群,这样另外一台没有备案无法通过域名访问的主机也可以发光发热不再吃灰了。

因此,这篇文档就是简单的记录一下,如何从 0 到 1 搭建一个 k3s 集群,并通过域名的方式对外提供服务。

k3s 是 k8s 的一个轻量化实现,去掉了一些功能,降低了对机器性能的要求,在基础的内容上并无太大差异差异

集群搭建

首先,我们先完成集群的搭建,我们需要准备两台机器,一台是 Master 节点,一台是普通的 Node 节点,k3s 会自动完成两台机器的负载均衡,决定每一个单元运行在哪台机器上。

k3s 的安装

Master节点的配置

首先,进入 Master 节点服务器,并依次执行以下命令:

# 安装K3s服务
curl -sfL https://get.k3s.io | sh -

# 配置文件添加符号链接,方便其他项目访问
ln -s /etc/rancher/k3s/k3s.yaml ~/.kube/config

# 安装完之后,查看节点状态,此时只有一个节点
kubectl get node

# 获取Token,用于下一步普通 Node 节点的配置
cat /var/lib/rancher/k3s/server/node-token

Node 节点的配置

# 同样执行安装程序
curl -sfL https://get.k3s.io | sh -

# 配置运行Agent,将master替换成Master节点的IP(内外网IP均可,需要保证能够相互通信),master-token替换成上一步获取到的A服务器的Token
k3s agent --server https://master-ip:6443 --token master-token

此时再次回到 Master 节点的服务器,可以执行 kubectl get node 查看是否关联成功,关联成功如下图

image-20211117205643993

注意:需要开放两台服务器的 TCP:6443、UDP:8472 端口,其中 6443 用于两个节点之间的信息同步,而 8472 端口用于 Master 节点获取另一个 Node 节点中 Pod 的数据

具体请参照:http://docs.rancher.cn/docs/rancher2/installation/requirements/ports/_index/

基本概念

接下来,我们讲解几个 k8s 中的概念。

Pod

Pod的概念

Pod是Kubernetes中能够创建和部署的最小单元,是Kubernetes集群中的一个应用实例,总是部署在同一个节点Node上。 Pod中包含了一个或多个容器,还包括了存储、网络等各个容器共享的资源。 Pod支持多种容器环境,Docker则是最流行的容器环境。 单容器Pod,最常见的应用方式。

上面贴上了网络上对 Pod 的定义,总的来说就是 Pod 是 k8s 中的最小单元,一般一个 Pod 只包含一个容器,比如一个前端项目就可以定义成一个 Pod。

在集群中,可以通过 kubectl get pods 来查询集群中部署的 Pod 有哪些

image-20211117184150956

如上图,我们可以看到,在我的集群中,部署了一个名叫 mdks-frontend 的 Pod

声明一个 Pod

在 k8s 中,我们习惯使用 yaml 文件来进行部署单元的声明,下面我们讲解如何通过 yaml 文件来声明一个 pod

  1. 创建 yaml 文件 vim show.yaml ,输入以下内容后保存

    apiVersion: v1 // api版本
    kind: Pod // 类型:Pod
    metadata:
    	name: nginx // Pod的名字
    spec:
    	containers:
    	- name: nginx // 容器名字
    	  image: nginx:latest // 容器镜像
    	  ports:
    	  - containerPort: 80 // 容器监听的端口
  2. 使用 kubectl 命令创建对应的 Pod kubectl apply -f ./showcase.yaml

image-20211117185038131

通过这两步,我们就完成了一个 Pod 的创建,可以通过 kubectl exec -it nginx -- /bin/bash 进行 Pod 查看是否可以正常运行

image-20211117185308476

如上图所示,我们通过命令进入了名为 nginx 的 Pod 内部,并通过 curl 命令请求自己,发现该容器内的 nginx 服务器是正常运转的。

到此为止,我们创建了一个功能正常的 Pod。

Deployment

上面我们讲了 Pod 的声明,实际上在公司内使用时,我们一般不会直接操作 Pod,而是常常使用 Deployment 来对 Pod 进行组织和拓展,比如最常见的扩容及缩容。

Deployment的概念

Deployment是一个定义及管理多副本应用(即多个副本 Pod)的新一代对象,与Replication Controller相比,它提供了更加完善的功能,使用起来更加简单方便。

它解决了ReplicaSet 更新的诸多问题,通过对ReplicaSet 和Pod 进行组装支持了滚动更新、回滚以及扩容等高级功能

在一个 k8s 集群中,我们可以通过 kubectl get deployment 来查看系统中已经存在的 Deployment

image-20211117190040778

从上图中,可以看到我们系统中目前只有一个叫 mdks-frontend 的 Deployment,下面我们手动创建一个新的 Pod。

声明一个 Deployment

  1. 与 Pod相同,首先我们也需要新建一个声明 Deployment 的 yaml 文件 deployment.yaml

  2. deployment.yaml 中键入以下内容

    apiVersion: apps/v1
    kind: Deployment // 声明类型
    metadata:
    	name: nginx // deployment的名字
    spec:
    	selector: // 定义选择器,用于控制创建的pod
    		matchLabels: // 匹配Pod的名字
    			app: nginx // Pod的名字
    	replicas: 2 // 创建几个副本
    	template: // 创建的Pod的模板属性
    		metadata:
    			labels: // 创建的Pod的label属性,需要与 Selector 中一致,否则无法管理
    				app: nginx
    		spec: // 与pod定义中的spec相同
    			containers:
    			- name: anyname // 这个容器的名字无所谓随便取
    			  image: nginx:latest
    			  ports:
    			  - containerPort: 80
  3. 指定 kubectl apply -f ./deployment.yaml 命令创建 Deployment,并查看

    image-20211117191331879

通过上面的命令我们就实现了一个 Deployment 的声明,并由该 Deployment 创建了两个 Pod,此时我们再通过 get pods 命令查看系统中的 Pod 会出现以下内容

image-20211117191539003

我们可以看到,在系统中存在三个以 nginx 开头的 Pod,其中第一个是我们手动创建的 Pod,而通过 Deployment 创建的 Pod 都会被命名为 ${DeploymentName}-${DeploymentUid}-${Hash} 这种格式。

每次我们通过对 Deployment 编辑来完成镜像的更新时,Pod 最后的 Hash 也会随之产生变化。

以上,就是一个 Deployment 的声明方式。

Service

Service的概念

Service是Kubernetes里最核心的资源对象之一,Service定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由Pod副本组成的集群实力。 Service与其后端Pod副本集群之间则是通过Label Selector来实现”无缝对接”。

简单来说,Service 是 Pod 对外服务所依赖的能力,所有外部服务通过或域名或 IP 来访问我们的前端资源,都需要经过 Service 的处理,而前端对服务端接口的调用也需要经过 Service 的中转,可以说 Service 是集群内信息交换的必要条件。

Service的定义

  1. 新建 Service 声明 yaml文件 service.yaml,并键入以下内容

    apiVersion: v1
    kind: Service // 类型 Service
    metadata:
    	name: nginx-svc
    spec:
    	selector: // 监听的Pod
    		app: nginx
    	ports:
    	- protocol: TCP // 接口协议
    	  port: 80 // service的端口
    	  targetPort: 80 // 容器的端口
    	  nodePort: 30080 // 容器对外直接提供服务的端口,可以通过服务器Ip:nodePort的方式访问
    	type: NodePort
  2. 执行 kubectl apply -f ./service.yaml 创建 Service,并通过 get svc 查看

    image-20211117193246949

如上我们就完成了一个最简单的 Service 的创建

在上面我们可以看到 Service 有两种类型,ClusterIPNodePort ,如果我们配置的是 NodePort 类型,此时通过服务器的 IP 地址和我们配置的 nodePort 端口号,就可以访问到我们系统内的服务了,如下图

image-20211117193547674

而如果我们选择的是 ClusterIP 类型,那么只会在集群内部可以访问到该 Pod,不会把 Pod 的内容映射在某一个外网可以访问的端口上,因此 ClusterIP 类型的 Service 配置文件如下:

apiVersion: v1
kind: Service // danyu
metadata:
	name: nginx-svc
spec:
	selector:
		app: nginx
	ports:
	- protocol: TCP // 接口协议
	  port: 80 // service的端口
	  targetPort: 80 // 容器的端口

ClusterIP 类型 Service 不代表着不能对外提供服务,而是需要 Ingress 的帮助,来将外网的流量转发到 Service 上来。

Ingress

Ingress的概念

Ingress 是对集群中服务的外部访问进行管理的API 对象,典型的访问方式是HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。

参照上面的定义,一般情况下我们会将 Service 定义为 ClusterIP ,并通过 Ingress 统一对外提供服务

Ingress的声明

  1. 新建 Ingress 声明 yaml 文件 ingress.yaml 并键入以下内容

    apiVersion: networking.k8s.io/v1
    kind: Ingress // 类型: Ingress
    metadata:
      name: nginx-ingress // Ingress的名字
    spec:
      rules: // 对外提供服务的规则
        - host: tianlu.live // 域名
          http: // 提供http服务
            paths:
              - path: /  // 规定请求的prefix
              	pathType: Prefix
                backend: 
                	service: // 指定后端 Service
                		name: nginx-svc // service名字
                		port:
                			number: 80 service监听的端口,与Service定义时相同
  2. 执行 kubectl apply -f ./ingress.yaml 命令创建 Ingress 并查看

    image-20211117195827198

将指定域名解析到集群 Master 节点的 IP 上,然后通过域名即可访问,如下图

image-20211117200137800

Secrets

Secrets 的概念

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。

Secrets 有很多细分的类型,在此篇文章中,我们仅用于配置域名的 HTTPS 访问

配置 HTTPS 访问

  1. 下载域名申请的 HTTPS 证书并保存在服务器中

  2. 在服务器中执行以下命令,需要将命令中的 cert/key 替换为你的证书路径,执行结果如下图

    kubectl create secret tls my-tls-secret \
      --cert=path/to/cert/file \
      --key=path/to/key/file

image-20211117202531838

  1. 执行 kubectl edit ingress nginx-ingress 编辑创建的 Ingress

    image-20211117202725873

​ 在 Ingress 配置文件中,添加 tls 模块并按照图上配置 hosts(域名,需要与rules中匹配才可使用证书),然后 设置 secretName 为创建的 Secret 即可。

​ 此时再次访问域名,即可切换为 HTTPS 访问

Powered By Hexo.js Hexo and Minima. Support By Oracle & Docker-Compose.

友情链接: 相随