拥抱K8S

介绍+搭建

传送门

  • 传统式部署:直接将应用程序部署在物理机上,很难合理性分配资源
  • 虚拟化部署:每个虚拟机都是一个独立的环境,解决了应用程序之间的影,一定程度上解决了资源,但增加了操作系统的部署
  • 容器化部署:类似虚拟化,但是共享了操作系统,而且可以跨云服务商、跨linux操作系统
    • 某个容器出故障宕机,另外一个容器立刻启动补上
    • 并发访问变大,如何做到横向扩展容器数量

最后的问题实则都是关于容器编排的问题

简介

容器化部署、管理、扩展,想想带环境安装,虽说docker也可以实现容器化的部署,但是还是需要一个完全功能的集群部署功能,而且k8s利于应用的扩展

主要特性

自动装箱:应用自动部署

自愈能力:当有容器失败的时候会对容器进行重启,有问题时,会重新部署和调度,未通过检查,会关闭该容器

水平扩展:根据简单命令和ui页面以及cpu使用情况,方便扩容和裁剪

服务发现:k8s自带发现服务功能和负载均衡

滚动更新:可根据应用变化,对容器运行应用进行批次或一次性更新,检测没有问题再更新

版本回退:历史版本记录,可以即时回退

密码配置管理:热部署,不需要重启

存储编排:支持存储本地、网络存储、公有云存储

批处理:支持一次性任务、定时任务

K8S组件

master(主控节点)和node(工作节点)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWS18P1x-1649685527859)(../ZNV/%E7%AC%94%E8%AE%B0%E5%9B%BE%E7%89%87/K8S/image-20220409103529253.png)]

master组件—管理

api server:集群的统一控制访问入口,以restful方式,交给etcd进行存储

scheduler:节点调度,选择节点应用部署

controller-manager:处理集群中常规的后台任务,一个资源对应一个控制器

形象理解三者关系,统一入口rest请求,scheduler选择某个节点,controller去在该节点上部署服务

etcd:存储状态类的数据,比如master、node的节点信息。有点类型元数据库,也可以替换成mysql或者其他数据库

node组件—具体工作者

kubelet:node里面的管理者,各种状态信息,节点用来管理容器

kube-proxy:提供网络代理,外部访问容器应用程序,负载均衡,类似nginx

docker:负责节点上容器的各种操作

核心概念

Pod:最小的部署单元,一组容器的集合,共享网络,生命周期短暂的

controller

  • 确保预期pod的副本的数量
  • 无状态的应用部署(一个节点挂了的容器自动在另外节点启动),有状态应用部署(需要特定条件,不考虑依赖性)
  • 确保所有的node运行同一个pod(比如多个节点运行同一个服务)
  • 可以创建一致性任务和定时任务

形象理解无状态,就是比如一个容器宕了,直接可以将运行该容器内的服务拿到其他容器运行,这就是无状态的

service:定义一组pod访问规则,不同服务请求不同的pod

下载部署

确保docker已安装完成

# 时间同步
yum install ntpdate -y
ntpdate time.windows.com

# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
setenforce 0  # 临时

# 关闭swap
swapoff -a  # 临时
sed -ri 's/.*swap.*/#&/' /etc/fstab    # 永久

# 三台节点/etc/hosts需要配置

# 将桥接的IPv4流量传递到iptables的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system  # 生效

# 配置阿里云yum源,方便安装
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# 安装1.18.0版本
yum install -y kubelet-1.18.0 kubeadm-1.18.0 kubectl-1.18.0

# 开机自启
systemctl enable kubelet

# 主节点启动 参数介绍:当前节点ip 国内镜像 k8s版本 可连接的ip网段
kubeadm init \
--apiserver-advertise-address=172.16.6.10 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.18.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config


# 使用kubectl工具
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 查看是否成功
kubectl get nodes

# 从节点加入主节点集群
kubeadm join 172.16.6.10:6443 --token jvdyus.xkae0oh1j7qkvluu \
    --discovery-token-ca-cert-hash sha256:b738b0598deb74177613994c9299f28a3899144e0d7e61da859b26d0768db148
    
# 如果产生报错[ERROR FileContent--proc-sys-net-ipv4-ip_forward]: /proc/sys/net/ipv4/ip_forw
sysctl -w net.ipv4.ip_forward=1

# 再次查看节点信息,没有准备好,需要进行下一步
[root@lv118 sysctl.d]# kubectl get nodes
NAME                STATUS     ROLES    AGE   VERSION
lv118.dct-znv.com   NotReady   master   10m   v1.18.0
lv121.dct-znv.com   NotReady   <none>   77s   v1.18.0
lv123.dct-znv.com   NotReady   <none>   14s   v1.18.0

# 部署CNI网络插件
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml

# 等待全部都是ready
kubectl get pods -n kube-system

# 再次查看节点信息
[root@lv118 sysctl.d]# kubectl get nodes
NAME                STATUS   ROLES    AGE     VERSION
lv118.dct-znv.com   Ready    master   18m     v1.18.0
lv121.dct-znv.com   Ready    <none>   9m21s   v1.18.0
lv123.dct-znv.com   Ready    <none>   8m18s   v1.18.0

# 测试k8s集群
kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --port=80 --type=NodePort

kubectl get pod,svc
# 任意一个节点访问80端口对外暴露端口,这里的是32574

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K9RPRMEf-1649685527861)(../ZNV/%E7%AC%94%E8%AE%B0%E5%9B%BE%E7%89%87/K8S/image-20220408213737868.png)]

二进制安装

资源管理

yaml书写介绍:https://www.bilibili.com/video/BV1Qv41167ck?p=13&share_source=copy_web

yaml转json的网站,可以通过它验证yaml是否书写正确https://www.json2yaml.com/convert-yaml-to-json

资源管理方式

kubectl是一个命令行工具

  • 命令式对象管理:直接用命令去操作kubernetes资源(命令行直接写参数)
kubectl run nginx-pod --image=nginx:1.17.1 --port=80
  • 命令式对象配置:通过命令配置和配置文件去操作kubernetes资源(通过配置文件)
kubectl create/patch -f nginx-pod.yaml
  • 声明式对象配置:通过apply命令和配置文件去操作kubernetes资源(只有一个apply关键字,只用于创建和更新资源,也就是该命令没有的时候创建,有了就表示更新)
kubectl apply -f nginx-pod.yaml

综上,第一个比较简单,一般用于测试,不能追踪;第二个适用于开发环境,可以直接定位追踪到文件配置,但项目较大的时候,文件过多;第三个适用于开发环境,支持目录的操作(yaml文件放在一个目录内,对目录进行操作,整体创建/更新)

命令式对象管理

kubectl [command] [type] [name] [flags]

# 查看所有的pod
kubectl get pod

# 差看某一个pod
kubectl get pod [pod_name]

# 查看某个pod所处节点
kubectl get pod [pod_name] -o wide

# 查看某个pod,以yaml格式展示结果
kubectl get pod [pod_name] -o yaml

# 查看资源
kubectl api-resources
资源分类资源名称缩写资源作用
集群级别资源nodesno集群组成部分
namespacesns隔离Pod
pod资源podspo装载容器
pod资源控制器replicationcontrollersrc控制pod资源
replicasetsrs控制pod资源
deploymentsdeploy控制pod资源
daemonsetsds控制pod资源
jobs控制pod资源
cronjobscj控制pod资源
horizontalpodautoscalershpa控制pod资源
statefulsetssts控制pod资源
服务发现资源servicessvc统一pod对外接口
ingressing统一pod对外接口
存储资源volumeattachments存储
persistentvolumespv存储
persistentvolumeclaimspvc存储
配置资源configmapscm配置
secrets配置
# 测试使用

# 创建一个dev的命名空间,ns是namespaces缩写,上表有提及
kubectl create ns dev

# 查看全部namespaces
kubectl get ns

# 在dev下创建一个pod
kubectl run pod --image=nginx -n dev

# 查看所创建的pod
kubectl get pods -n dev

# 查看创建该pod的详细信息
kubectl describe pods pod -n dev

# 删除该创建的pod
kubectl delete pods pod -n dev

# 删除空间dev
kubectl delete ns dev

命令式对象配置

# 创建nginxpod.yaml文件,写入如下内容
apiVersion: v1
kind: Namespace
metadata:
  name: dev

---

apiVersion: v1
kind: Pod
metadata:
  name: nginxpod
  namespace: dev
spec:
  containers:
  - name: nginx-containers
    image: nginx:latest

# 创建资源
kubectl create -f nginxpod.yaml

# 删除资源
kubectl delete -f nginxpod.yaml

声明式对象配置

# 利用前文提及yaml文件进行创建
kubectl apply -f nginxpod.yaml

# 查看资源
kubectl get pods -n dev

# 再次执行,会进行更新操作,因为已存在,如果没有变化会显示unchanged,有变动会显示configured
kubectl apply -f nginxpod.yaml

以上操作都是在主节点进行,如果需要从节点执行,需要拷贝主节点用户目录下的.kube文件到从节点用户目录下

逻辑概念

namespace

实现多套环境的资源隔离和多租户的资源隔离

  • namespace用于将pod划分为逻辑上的分组,以便于实现不同组之间的资源隔离
  • namespace也可对不同的租户进行管理,限制不同租户所占用的资源,例如cpu核数、内存使用
# 查看namespace,k8s启动时会有几个默认的namespace
kubectl get ns

default           #  所有未指定Namespace的对象都会被分配在default命名空间
kube-node-lease   #  集群节点之间的心跳维护,v1.13开始引入
kube-public       #  此命名空间下的资源可以被所有人访问(包括未认证用户)
kube-system       #  所有由Kubernetes系统创建的资源都处于这个命名空间

# 查看某一ns详情
kubectl get ns default

Name:         default
Labels:       <none>
Annotations:  <none>
Status:       Active    # Active 命名空间正在使用中  Terminating 正在删除命名空间
No resource quota.      # ResourceQuota 针对namespace做的资源限制
No LimitRange resource. # LimitRange针对namespace中的每个组件做的资源限制

# 查、创、删 命令行
[root@lv118 disk3]# kubectl create ns dev
namespace/dev created
[root@lv118 disk3]# kubectl get ns dev
NAME   STATUS   AGE
dev    Active   10s
[root@lv118 disk3]# kubectl delete ns dev
namespace "dev" deleted

# 查、创、删 yaml文件
[root@lv118 disk3]# cat ns-dev.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: dev

[root@lv118 disk3]# kubectl create -f ns-dev.yaml
namespace/dev created
[root@lv118 disk3]# kubectl get ns dev
NAME   STATUS   AGE
dev    Active   12s
[root@lv118 disk3]# kubectl delete -f ns-dev.yaml
namespace "dev" deleted

pod

pod是k8s最小单元,应用程序跑在容器内,容器存在pod内,所以一个pod可以有多个容器

# 创建并运行指定镜像的pod
kubectl run nginx --image=nginx --port=80 --namespace dev

# 查看pod相关信息
kubectl get pods -n dev -o wide

# 查看pod详细信息
kubectl describe pod nginx -n dev

# 删除pod
kubectl delete pod nginx -n dev
# 旧版本删完还存在,是因为后台是存在一个控制器,删除立马重启,这里需要删除控制器,就可删除干净(新版本忽略)
kubectl delete deploy nginx -n dev

# yaml文件形式创建
cat pod-nginx.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: dev
spec:
  containers:
  - image: nginx:latest
    name: pod
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP
[root@lv118 disk3]# kubectl create -f pod-nginx.yaml
pod/nginx created
[root@lv118 disk3]# kubectl get pods -n dev
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          9s
[root@lv118 disk3]# kubectl delete -f pod-nginx.yaml
pod "nginx" deleted

Label

label的作用在于给资源添加标识,和用于区分选择,和namespace不同的是这是可以互相通信的,由于在功能上不同,所以用以标签区别

  • 基于等式的标签选择器,选择所有包含Label中key="name"且value="slave"的对象
  • 基于集合的标签选择器 name in (master,slave):选择所有label中key="name"且value="master"或"slave"的对象
# 查看pod打标签
[root@lv118 disk3]# kubectl get pod -n dev --show-labels
NAME    READY   STATUS    RESTARTS   AGE     LABELS
nginx   1/1     Running   0          3m14s   <none>

# 打标签
[root@lv118 disk3]# kubectl label pod nginx -n dev version=1.0
pod/nginx labeled

# 再次查看
[root@lv118 disk3]# kubectl get pod -n dev --show-labels
NAME    READY   STATUS    RESTARTS   AGE     LABELS
nginx   1/1     Running   0          3m56s   version=1.0

# 修改标签
[root@lv118 disk3]# kubectl label pod nginx -n dev version=2.0 --overwrite
pod/nginx labeled

# 再次查看
[root@lv118 disk3]# kubectl get pod -n dev --show-labels
NAME    READY   STATUS    RESTARTS   AGE     LABELS
nginx   1/1     Running   0          5m22s   version=2.0

# 再添加一个pod,记得修改yaml文件内pod名字
# 将新pod增加版本,结果最后如下
[root@lv118 disk3]# kubectl get pod -n dev --show-labels
NAME     READY   STATUS    RESTARTS   AGE     LABELS
nginx    1/1     Running   0          7m36s   version=2.0
nginx1   1/1     Running   0          60s     version=1.0

# 查询指定范围标签的pod
[root@lv118 disk3]# kubectl get pods -l version!=1.0  -n dev --show-labels
NAME    READY   STATUS    RESTARTS   AGE   LABELS
nginx   1/1     Running   0          13m   version=2.0


# 删除某个标签
[root@lv118 disk3]# kubectl label pod nginx -n dev version-

# pod-nginx.yaml文件配置
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: dev
  labels:
    version: "3.0"
    env: "test"
spec:
  containers:
  - image: nginx:latest
    name: pod
    ports:
    - name: nginx-port
      containerPort: 80
      protocol: TCP
# 更新
kubectl apply -f pod-nginx.yaml
#再次查看
[root@lv118 disk3]# kubectl get pods -n dev --show-labels
NAME     READY   STATUS    RESTARTS   AGE   LABELS
nginx    1/1     Running   0          22m   env=test,version=3.0

Deployment

pod虽然作为k8s中最小控制单元,但k8s却很少去直接控制,一般都是通过pod控制器来完成,pod控制器用于pod的管理,当pod故障时,会尝试重启/重建pod

# 创建Deployment
kubectl create deployment nginx --image=nginx -n dev

# 删除Deployment
kubectl delete deploy nginx -n dev


# deploy-nginx.yaml文件配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: dev
spec:
  replicas: 3
  selector:
    matchLabels:
      run: nginx
  template:
    metadata:
      labels:
        run: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
          protocol: TCP
# 运行文件
kubectl create -f deploy-nginx.yaml
# 查看
kubectl get deployment,pods -n dev

Service

利用pod控制器可以很轻松让挂掉的pod重新启动,但是如果我们访问的是之前旧的podip端口,这样一重启岂不是ip都变了嘛

service可以看作是一组同类pod对外访问的接口,接助service,应用可以很方便的实现服务发现和负载均衡,同类指的是标签,serviceip是不变的

# 1、集群内部访问
# 创建service
kubectl expose deploy nginx --name=svc-nginx1 --type=ClusterIP --port=80 --target-port=80 -n dev

# 查看service
[root@lv118 disk3]# kubectl get svc svc-nginx1 -n dev -o wide
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE   SELECTOR
svc-nginx1   ClusterIP   10.96.19.197   <none>        80/TCP    4m    run=nginx

# 访问service的ip和端口
[root@lv118 disk3]# curl 10.96.19.197:80

# 2、外部访问
[root@lv118 disk3]# kubectl expose deploy nginx --name=svc-nginx2 --type=NodePort --port=80 --target-port=80 -n dev
[root@lv118 disk3]# kubectl get svc -n dev
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
svc-nginx1   ClusterIP   10.96.19.197     <none>        80/TCP         6m39s
svc-nginx2   NodePort    10.110.163.156   <none>        80:30419/TCP   13s
# 本机浏览器访问,注意端口来自上文的svc端口
master服务器地址:30419


# 删除service
[root@lv118 disk3]# kubectl delete svc svc-nginx2 -n dev
service "svc-nginx2" deleted
[root@lv118 disk3]# kubectl delete svc svc-nginx1 -n dev
service "svc-nginx1" deleted


# svc-nginx.yaml文件
apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
  namespace: dev
spec:
  clusterIP: 10.109.179.231 #固定svc的内网ip
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    run: nginx
  type: ClusterIP
# 执行文件
kubectl create -f svc-nginx.yaml
# 查看
kubectl get svc -n dev

Pod详述

pod配置项

apiVersion: v1     #必选,版本号,例如v1
kind: Pod         #必选,资源类型,例如 Pod
metadata:         #必选,元数据
  name: string     #必选,Pod名称
  namespace: string  #Pod所属的命名空间,默认为"default"
  labels:           #自定义标签列表
    - name: string                 
spec:  #必选,Pod中容器的详细定义
  containers:  #必选,Pod中容器列表
  - name: string   #必选,容器名称
    image: string  #必选,容器的镜像名称
    imagePullPolicy: [ Always|Never|IfNotPresent ]  #获取镜像的策略 
    command: [string]   #容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]      #容器的启动命令参数列表
    workingDir: string  #容器的工作目录
    volumeMounts:       #挂载到容器内部的存储卷配置
    - name: string      #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean #是否为只读模式
    ports: #需要暴露的端口库号列表
    - name: string        #端口的名称
      containerPort: int  #容器需要监听的端口号
      hostPort: int       #容器所在主机需要监听的端口号,默认与Container相同
      protocol: string    #端口协议,支持TCP和UDP,默认TCP
    env:   #容器运行前需设置的环境变量列表
    - name: string  #环境变量名称
      value: string #环境变量的值
    resources: #资源限制和请求的设置
      limits:  #资源限制的设置
        cpu: string     #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string  #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests: #资源请求的设置
        cpu: string    #Cpu请求,容器启动的初始可用数量
        memory: string #内存请求,容器启动的初始可用数量
    lifecycle: #生命周期钩子
        postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
        preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
    livenessProbe:  #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
      exec:         #对Pod容器内检查方式设置为exec方式
        command: [string]  #exec方式需要制定的命令或脚本
      httpGet:       #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0       #容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0          #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0           #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged: false
  restartPolicy: [Always | Never | OnFailure]  #Pod的重启策略
  nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
  nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
  imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
  - name: string
  hostNetwork: false   #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
  volumes:   #在该pod上定义共享存储卷列表
  - name: string    #共享存储卷名称 (volumes类型有很多种)
    emptyDir: {}       #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
    hostPath: string   #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
      path: string                #Pod所在宿主机的目录,将被用于同期中mount的目录
    secret:          #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
      scretname: string  
      items:     
      - key: string
        path: string
    configMap:         #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
      name: string
      items:
      - key: string
        path: string
Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐