02 k8s

入门篇

架构与组件

来源于网络

管理节点 master

API server

集群的统一入口,各个组件的协调者,Restful的形式提供接口服务。所有对象的增删改查和监听操作都交给Api Server处理后,存储在Etcd中

Controller-manager

处理常规后台任务:容器的部署、扩容副本、服务升级等,一个资源对应一个congtroller。比如一个Pod有3个副本,一个挂掉了,就会再创建一个), ControllerManager就是管理这些controller。

Scheduler

根据调度算法将创建的Pod调度到适合的机器节点上,比如按照容器数量调度等等

Etcd

分布式存储组件,集群状态数据持久化,只有API Server可以用。比如Pod,serverie等的信息

工作节点 worker

Kube-let

与master节点交互,管理当前工作节点上运行的Pod的生命周期,比如创建,挂载数据卷,下载secret,获取Pod和节点状态。接收API Server的请求,在本地调用docker的Api,执行具体的命令

Kube-proxy

负责各个Pod的网络通信,接收浏览器发出请求,负载到具体的Pod的

回顾

来源于网络

安装

二进制安装

优缺点:手动部署每个组件,手动编写每个组件的配置文件,前期部署难度大,后期维护轻松

Rancher安装

https://blog.csdn.net/cdy2143/article/details/109534036

Kube-admin安装

优缺点:用于快速部署k8s集群的工具,简化部署集群,后期维护比较难

准备

  • 3台机器:1主2从
  • 禁止swap分区:当物理内存不足,使用磁盘作为交换数据

安装

# 关闭防火墙

systemctl stop firewalld 临时

systemctl disable firewalld 永久

# 关闭安全模块selinux

setenforce 0 临时

https://jingyan.baidu.com/article/7e4409537177d32fc0e2efe9.html 永久

getenforce 查看

# 禁止swap分区

swapoff -a 临时

https://blog.csdn.net/yefun/article/details/102772368 永久

free -m 查看状态

# 添加ipv4流量同步iptables,k8s使用iptables网络

cat >> /etc/sysctl.d/k8s.conf << EOF

net.bridge.bridge-nf-call-ip6tables=1

net.bridge.bridge-nf-call-iptables=1

EOF

sysctl -p /etc/sysctl.d/k8s.conf 生效

拓展:sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: 没有那个文件或目录报错

解决:modprobe br_netfilter

参考:https://www.cnblogs.com/EasonJim/p/9626986.html重启生效

# 时间同步  yum install ntpdate -y

ntpdate time.windows.com

# 安装docker

https://www.jianshu.com/p/c6c56194252e

# 安装k8s

# 添加阿里云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

# 安装工具kubeadm、kubelet、kubectl

yum install -y kubelet-1.19.0 kubeadm-1.19.0 kubectl-1.19.0

systemctl enable kubelet 开机启动

# 以上为通用设置 先设置通用部分作为虚拟机模板,只改需要的部分

# 设置主机名

hostnamectl set-hostname k8swork02 名

# 添加hosts

cat >> /etc/hosts << EOF

192.168.207.129 k8smaster

192.168.207.134 k8swork01

192.168.207.135 k8swork02

EOF

# 安装k8smaster

kubeadm init \

  --apiserver-advertise-address=192.168.31.61 \ 集群入口地址

  --image-repository registry.aliyuncs.com/google_containers \ 设置阿云镜像

  --kubernetes-version v1.19.0 \ 设置版本,要与上面一致

  --service-cidr=10.96.0.0/12 \ service网络地址

  --pod-network-cidr=10.244.0.0/16 \ pod网络地址

  --ignore-preflight-errors=all 

mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 加入工作节点,master节点创建后会返回

kubeadm join 192.168.207.129:6443 --token gedbw8.8y6gnfwdl78ec69l \

    --discovery-token-ca-cert-hash sha256:0083a787f58a3afb57b7dc42d526d4943c1b4fb60abc04a839f29ef476e57192

# 这里的token有效期24小时,一旦过期就要重新创建

kubeadm token create

kubeadm token list

# 查看集群节点,这是节点not ready 因为pod网络不能连通

kubectl get nodes

# 在master安装网络插件,集群连通

wget [https://docs.projectcalico.org/manifests/calico.yaml](https://docs.projectcalico.org/manifests/calico.yaml)

# 下载完后还需要修改里面定义Pod网络(CALICO_IPV4POOL_CIDR),与前面kubeadm init指定Pod网络的一样
# 修改完后应用清单:
kubectl apply -f calico.yaml
kubectl get pods -n kube-system

# 7. 测试kubernetes集群
# 创建pod
kubectl create deployment nginx --image=nginx 
# 创建service port集群内部访问,target-port容器内部端口,NodePort外部端口随机生成
kubectl expose deployment nginx --port=80 --target-port=80 --type=NodePort
# 查看pod,sevice 
kubectl get pod,svc,deployment,namespace

部署java应用

  1. 创建docker镜像
    参考:https://www.jianshu.com/p/c6c56194252e

  2. 控制管理器pod

kubectl create deployment k8sdemo --image k8sdemo:1.0 --dry-run -o yaml > k8sdemo.yml  输出yaml文件,不生产pod资源

kubectl apply -f k8sdemo.yml 执行yaml文件,生产pod资源,这时是不能对外访问的
  1. 暴露应用service
kubectl expose deployment k8sdemo --port=8080 --target-port=8080 --type=NodePort --dry-run -o yaml > k8s_svc.yml 输出yaml文件,不生产service资源

kubectl apply -f k8sdemo.yml 执行yaml文件,生产service资源,集群内部访问,外部访问

# 编辑yaml https://www.cnblogs.com/plefan/p/14149752.html
  1. 对外发布应用

  2. 日志监控

K8s的资源

Namespace对象

主要作用:用来实现多套环境的资源隔离,或者多租户下的资源隔离。
默认情况下,k8s集群中的所有pod都是可以相互访问的,因为都属于同一个namespace= default。但实际上可能需要pod之间的相互隔离。

Pod对象

为什么有?

1.K8s中最小部署单元
2.一个容器或多个容器的集合
3.Pod中的容器,网络命名空间(socket/127.0.0.1本地连接)与存储是共享的
docker 容器,一个容器只运行一个应用程序进程。pod容器,一个容器可以运行多个应用程序进程。只要为比较亲密的应用程序而设计,比如2个应用程序之间存在文件交互,网络通信,频繁调用等等。

网络共享

Pod底层采用docker容器,可是docker容器之间是隔离的,那么pod是怎么做到网络共享的呢?
解决:docker容器隔离底层实现采用linux的namespace资源隔离机制,让每个docker容器都有自己的ip,port,mac等。
而每个pod容器则是默认创建一个pause容器,将业务容器都加入到这个默认容器中 (docker的一种网络:–net=container),这样所有容器都在同一个namespace下,所有容器都享有相同的ip,port,mac等。


参考:https://network.51cto.com/art/202007/620287.htm?mobile

存储共享

数据卷

比如pod在A机器上部署,突然宕掉了,k8s在B机器上拉起了一个,那么之前的数据可定就丢失了,这个肯定是不对的。
将pod中的数据远程存储在某个地方,即挂载。
Pod容器间的数据卷挂载,2个容器挂载相同数据目录。

几种数据卷

  • emptydir :Pod容器内部数据卷,共享容器内部文件,pod被删除数据卷也会被删除。主要用于某些应用程序无需永久保存的临时目录,多个docker容器的共享目录等。
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8sdemo
  name: k8sdemo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8sdemo
  template:
    metadata:
      labels:
        app: k8sdemo
    spec:
      containers:
      - image: k8sdemo:1.0
        name: k8sdemo
        volumeMounts:
          - mountPath: /mycachedata
            name: mycache
      - image: nginx
        name: nginx
        volumeMounts:
          - mountPath: /mycachedata
            name: mycache
      volumes:
        - name: mycache
          # pod内容器数据共享,pod删除数据删除
          emptyDir: {}
  • hostPath: 机器节点上数据卷,共享host机器上文件
spec:
  containers:
  - image: k8sdemo:1.0
    name: k8sdemo
    volumeMounts:
      # 指定在容器中挂接路径
      - mountPath: /myhostdata
        name: myhostcache
  - image: nginx
    name: nginx
    volumeMounts:
      - mountPath: /myhostdata
        name: myhostcache
  volumes:
    - name: myhostcache
      # 主机上共享数据卷,pod删除数据不删除;
      # 主机宕机,数据丢失/pod被其他主机拉起,数据丢失
      hostPath:
        # 动作节点上目录必须存在,否则报错
        path: /home/k8sdir/demo/myhostdata
  • nfs : 远程存储数据卷,共享远程集群的文件。在YAML文件指定使用名称为nfs的PersistenVolumeClaim对容器的数据进行持久化。
volumes:
  - name: mynfs
    nfs:
      path: /xxx
      server: 0.0.0.0
    #指定使用PersistenVolumeClaim对容器的数据进行持久化。
    persistentVolumeClaim:
      claimName: xxx
  • Secret :加密数据卷
volumes:
  - name: mysecret
    secret:
      secretName: set

参考链接:https://www.cnblogs.com/hongdada/p/11586514.html

Deployment控制器

K8s的控制器之一,管理pod对象,主要部署无状态应用,比如web、api等。
Pod Yaml文件中指定控制器,并为pod贴上标签,同时指定控制器要找的pod的标签。


来源于网络

Pod与controller的关系

Controller,又叫workload,主要是管理和运行集群上的pod容器对象,可以实现容器的动态扩缩容,回滚等

最常用的Deployment的功能与应用场景

1.部署无状态应用
2.管理pod和replicaSet
3.上线部署,副本数量,滚动更新,回滚等
应用场景:web服务,微服务等http服务

Yaml解析

来源于网络

使用deployment部署无状态应用

kubectl create deployment web --image=nginx --dry-run -o yaml > web-pod.yaml

kubectl expose deployment web --port=80 --target-port=90 -dry-run -o yaml -type=NodePort > web-sev.yaml

升级与回滚

本质上还是重新部署一个新的镜像,或者回滚到之前的镜像,这里相当于只是修改pod容器的镜像资源,不能直接修改service。一般service只是用来暴露应用的,基本不动。

升级

动态滚动升级镜像,会创建一个容器,当这个容器运行状态,就会删除原有的容器

kubectl set image deployment web nginx=nginx:1.15.0

直接在线编辑,保存之后直接应用

kubectl edit deployment web(pod) / kubectl edit svc web(service)
回滚
# 查看历史记录
kubectl rollout history deployment web 
# 回滚
kubectl rollout undo deployment web 回滚到上一个版本
kubectl rollout undo deployment web --to-revision=1 回滚指定版本
删除
# 不能直接删除pod,因为指定副本后k8s会自动拉起一个
kubectl delete deployment web 
kubectl delete svc web

弹性伸缩

扩容
# 只是扩展集群的pod容器数量,不是扩展集群中的机器数量
kubectl scale deployment web --replicas=5

金丝雀发布

比如:有一批pod需要更新,但在更新极少部分时把它暂停住,这样有一小部分是新的pod,有大多数是旧的pod。可以一小部分请求去了新的版本,其他请求还在旧的版本。如果新的版本出现了问题,就立即回滚,如果没有问题就继续全部更新。就是金丝雀发布,先极小部分更新,后全部更新或者回滚。


来源于网络
命令
###### 暂停发布

kubectl set image deploy myapp-deploy myapp=ikubernetes/myapp:v2 && kubectl rollout pause deploy myapp-deploy

###### 继续发布

kubectl rollout resume deploy myapp-deploy 

这是新旧版本一起进行工作,,比如原先有10个pod。新的2个,旧的应该是8个。根据这个原理可以实现灰度发布,蓝绿发布。。
灰度2种方式
 spec.strategy灰度发布:https://cloud.tencent.com/developer/article/1644128

Ingress-nginx转发请求:https://www.freesion.com/article/62471221222/

Service对象

为什么有?

k8s部署一个服务,会有多个pod提供服务,根据调度策略分布在不同的机器节点上。
参考:https://www.cnblogs.com/peng-zone/p/11739433.html

Pod分布在不同的机器上,通过service进行均衡请求,定位机器。

Service的功能
1,能够动态感知集群中的pod数量,ip,端口等
2,负载均衡
3,提供暴露规则,访问pod:clusterIp集群中,nodeport外部应用,localbalancer负载均衡

Service怎么与pod关联?

依旧是通过标签,获取一组pod


3种暴露应用类型
  • clusterIp:集群内部产生ip,监听端口,负载均衡内部请
  • Nodeport:主机节点暴露端口,外部访问
  • Loadbalancer:主要为公有云预留,负载均衡做一个集成
Service怎么实现负载均衡

内部维护一张iptables路由转发规则,由LVS(ipvs)负载均衡,大并发下快速转发请求。这里集群任何一个节点service都可以转发,这里需要打通pod之间的网络连通,pod与机器节点的网络连通。


Ingress

参考链接:https://www.cnblogs.com/linuxk/p/9706720.html

Service暴露服务给外部访问,NodePort、loadBalancer。Nodeport则是是将集群内部的服务,监听一个端口,进而供外部访问,浪费集群机器的端口;loadbalancer则是需要一个外部的LB设备支持,过于麻烦。

Ingress,对象资源。只需要一个nodeport或loadbalancer,访问多个service,来解决这种痛点。 底层实现就是通过nginx,进行反向代理,创建不同的域名规则,映射到不同的service。

Ingress Controller,资源控制器。监听并解析ingress定义的规则,并转发请求到具体service。

来源于网络

  1. 环境安装,部署nginx ingress controller(nginx)

参考:https://www.cnblogs.com/panwenbin-logs/p/9915927.html

注意

a. mantory.yml 地址:https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.20.0/deploy/mandatory.yaml

b. 复制到idea中修改报错地方为apps/v1

c. 之后按照文档中来做就可以了。

  1. 创建ingress规则
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-rule
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
    - host: www.123.cn
      http:
        paths:
          - backend:
              serviceName: k8sdemo
              servicePort: 8080
  1. hosts中配置www.123.cn映射,之后请求 http://www.123.cn:32080/hello,32080是nginx的http端口。之后的service type=clusterip,只集群内部访问,在ingress-rule中设置相对映射就可以了。

以上k8s入门基本完成,一个服务一个服务的部署,已经可以搭建项目了,可以试着做一个自己的项目。。参考实战篇:springboot项目

高级篇

界面管理

Dashboard

  1. 下载文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
  1. 修改文件
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: 8443
      nodePort: 30001
  selector:
    k8s-app: kubernetes-dashboard
  type: NodePort
  1. 创建应用
$ kubectl apply -f recommended.yaml

$ kubectl get pods -n kubernetes-dashboard
  1. 访问地址:https://NodeIP:30001
# 创建用户

$ kubectl create serviceaccount dashboard-admin -n kube-system

# 用户授权

$ kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin

# 获取用户Token

$ kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')

Rancher

参考:https://blog.csdn.net/cdy2143/article/details/109534036

Master高可用

多服务部署

实战篇

springboot项目

环境:Springweb + mysql

mysql.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: mydb
  name: mydb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mydb
  template:
    metadata:
      labels:
        app: mydb
    spec:
      # 指定节点部署pod:https://blog.csdn.net/anqixiang/article/details/114151517
      nodeSelector:
        nodetype: "db"
      #      nodeName: "k8swork01"
      containers:
        - image: mysql:5.7
          name: mysql
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /var/lib/mysql
              name: dbdata
            - mountPath: /etc/mysql/conf.d
              name: dbconf
          env:
            - name: "MYSQL_ROOT_PASSWORD"
              value: "111111"
          ports:
            - containerPort: 3306
      volumes:
        - name: dbdata
          hostPath:
            path: /home/k8sdir/mysql/data
        - name: dbconf
          hostPath:
            path: /home/k8sdir/mysql/conf
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: mydb
  name: mydb
spec:
  ports:
    - port: 3306
      protocol: TCP
      targetPort: 3306
      nodePort: 30306
  selector:
    app: mydb
  type: NodePort

demo.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8sdemo
  name: k8sdemo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8sdemo
  strategy: {}
  template:
    metadata:
      labels:
        app: k8sdemo
    spec:
      nodeName: "k8smaster"
      containers:
        - image: k8sdemo:3.0
          name: k8sdemo
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: k8sdemo
  name: k8sdemo
spec:
  ports:
    - port: 8080
      protocol: TCP
      targetPort: 8080
      nodePort: 30080
  selector:
    app: k8sdemo
  type: NodePort

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    # mydb是service名称,3306是service的端口
    url: jdbc:mysql://mydb:3306/k8s_db
    username: root
    password: 111111

你可能感兴趣的:(02 k8s)