K8S原理以及概念

基本概念:

使用集群可以做到统一对外提供接口,无须进行各种复杂的调用;提供更好的可靠性,服务器宕机那 么频繁,物理磁盘那么容易损坏,无须担心,集群统一进行调配;提供更好的性能,组合集群中各个机 器的计算存储网络资源,提供更好的TPS和PS;提供横向扩容的能力,在进行横向扩容的时候,性能基 本上能呈线性增长。

k8s三master架构 k8s架构原理_k8s三master架构

可以看到k8s在物理上进行划分的时候,划分了两种类型的主机,一个master节点,主要用来调度, 控制集群的资源等功能;而node节点,主要是用来运行容器的节点,也就是运行服务的节点。

基本部署:

部署完成应用之后,就可以看到应用的名称,Deployment期望状态是运行一个pod,就会运行有一个 pod,活动的也是一个

k8s三master架构 k8s架构原理_kubernetes_02

在k8s里面,集群调度的最小单元就是一个pod,一个pod可以是一个容器,也可以是多个容器,例如 你运行一个程序,其中使用了nginx,使用mysql了,使用了jetty,那么可以将这三个使用在同一个pod 中,对他们提供统一的调配能力,一个pod只能运行在一个主机上,而一个主机上可以有多个pod。

k8s三master架构 k8s架构原理_kubernetes_03

每个pod也有独一的ip地址,当有多个pod提供相同的服务的时候,就需要有负载均衡的能力,从而 这里就涉及到一个概念就是service,专门用来提供服务的。服务主要是用来提供外界访问的接口,服务 可以关联一组pod,这些pod的ip地址各不相同,而service相当于一个复杂均衡的vip,用来指向各个 pod,当pod的ip地址发生改变之后,也能做到自动进行负载均衡,在关联的时候,service和pod之间主 要通过label来关联,也就是标签(-l表示为label)。

k8s三master架构 k8s架构原理_kubernetes_04

K8S角色:

  1. cluster cluster是 计算、存储和网络资源的集合,k8s利用这些资源运行各种基于容器的应用。
  2. master master是cluster的大脑,他的主要职责是调度,即决定将应用放在那里运行。master运行linux操作系 统,可以是物理机或者虚拟机。为了实现高可用,可以运行多个master。
  3. node node的职责是运行容器应用。node由master管理,node负责监控并汇报容器的状态,同时根据 master的要求管理容器的生命周期。node运行在linux的操作系统上,可以是物理机或者是虚拟机。
  4. pod pod是k8s的最小工作单元。每个pod包含一个或者多个容器。pod中的容器会作为一个整体被master调 度到一个node上运行。
  5. controller k8s通常不会直接创建pod,而是通过controller来管理pod的。controller中定义了pod的部署特性,比如 有几个剧本,在什么样的node上运行等。为了满足不同的业务场景,k8s提供了多种controller,包括 deployment、replicaset、daemonset、statefulset、job等。
1.deployment
#是最常用的controller deployment可以管理pod的多个副本,并确保pod按照期望的状态运行。

2.replicaset
#实现了pod的多副本管理。使用deployment时会自动创建replicaset,也就是说deployment是通过replicaset来管理pod的多个副本的,我们通常不需要直接使用replicaset。

3.daemonset
#用于每个node最多只运行一个pod副本的场景。正如其名称所示的,daemonset通常用于运行daemon。

4.statefuleset
#能够保证pod的每个副本在整个生命周期中名称是不变的,而其他controller不提供这个功能。当某个pod发生故障需要删除并重新启动时,pod的名称会发生变化,同时statefulset会保证副本按照固定的顺序启动、更新或者删除。

5.job
#用于运行结束就删除的应用,而其他controller中的pod通常是长期持续运行的。

6.service k8s的 service定义了外界访问一组特定pod的方式。service有自己的IP和端口,service为pod提供了负 载均衡。k8s运行容器pod与访问容器这两项任务分别由controller和service执行。

Service 有四种类型:
#1.ClusterIP:默认类型,自动分配一个仅 cluster 内部可以访问的虚拟 IP

#2.NodePort:在 ClusterIP 基础上为 Service 在每台机器上绑定一个端口,这样就可以通过NodeIP:NodePort 来访问该服务。如果 kube-proxy 设置了 –nodeport-addresses=10.240.0.0/16(v1.10 支持),那么仅该 NodePort 仅对设置在范围内的 IP 有效。

#3.LoadBalancer:在 NodePort 的基础上,借助 cloud provider 创建一个外部的负载均衡器,并将请求转发到 :NodePort

#4.ExternalName:将服务通过 DNS CNAME 记录方式转发到指定的域名(通过 spec.externlName 设定)。需要 kube-dns 版本在 1.7 以上。

7.namespace 可以将一个物理的cluster逻辑上划分成多个虚拟cluster,每个cluster就是一个namespace。不同的 namespace里的资源是完全隔离的。

k8s的集群部署 基础环境配置

基础环境配置

#修改host
vim /etc/hosts
10.0.0.50 k8s-master
10.0.0.51 k8s-node-01
10.0.0.52 k8s-node-02

#修改 10.0.0.50 服务器,设置 hostname,然后将 hostname 写入 hosts
$ hostnamectl set-hostname k8s-master
$ echo "127.0.0.1 $(hostname)" >> /etc/hosts

#修改 10.0.0.51 服务器,设置 hostname,然后将 hostname 写入 hosts
$ hostnamectl set-hostname k8s-node-01
$ echo "127.0.0.1 $(hostname)" >> /etc/hosts

#修改 10.0.0.52 服务器,设置 hostname,然后将 hostname 写入 hosts
$ hostnamectl set-hostname k8s-node-02
$ echo "127.0.0.1 $(hostname)" >> /etc/hosts

#时间同步
systemctl start chronyd.service && systemctl enable chronyd.service

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

#关闭selinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

#禁用swap
swapoff -a && sysctl -w vm.swappiness=0
vi /etc/fstab
/dev/mapper/centos-swap swap swap defaults 0 0

#配置内核参数:
$ cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
EOF
#使配置生效:

#挂载 br_netfilter
$ modprobe br_netfilter
#使配置生效
$ sysctl -p /etc/sysctl.d/k8s.conf
#查看是否生成相关文件
$ ls /proc/sys/net/bridge

#由于ipvs已经加入到了内核的主干,所以为kube-proxy开启ipvs的前提需要加载以下的内核模块:
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack_ipv4
$ cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
#执行脚本并查看是否正常加载内核模块:
#修改脚本权限
$ chmod 755 /etc/sysconfig/modules/ipvs.modules
#执行脚本
$ bash /etc/sysconfig/modules/ipvs.modules
#查看是否已经正确加载所需的内核模块
$ lsmod | grep -e ip_vs -e nf_conntrack_ipv4

#安装 ipset 和 ipvsadm
$ yum install -y ipset ipvsadm
#配置资源限制
echo "* soft nofile 65536" >> /etc/security/limits.conf
echo "* hard nofile 65536" >> /etc/security/limits.conf
echo "* soft nproc 65536" >> /etc/security/limits.conf
echo "* hard nproc 65536" >> /etc/security/limits.conf
echo "* soft memlock unlimited" >> /etc/security/limits.conf
echo "* hard memlock unlimited" >> /etc/security/limits.conf

#安装依赖包以及相关工具
yum install -y epel-release
yum install -y yum-utils device-mapper-persistent-data lvm2 net-tools conntracktools wget vim ntpdate libseccomp libtool-ltdl
#由于官方下载速度比较慢,所以需要更改 Docker 安装的 yum 源,这里推荐用阿里镜像源:
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装指定版本 docker
#注意:安装前一定要提前查询将要安装的 Kubernetes 版本是否和 Docker 版本对应。
yum install -y docker-ce-18.09.9-3.el7

#设置镜像存储目录,找到大点的挂载的目录进行存储
$ vi /lib/systemd/system/docker.service
#找到这行,往后面加上存储目录,例如这里是 --graph /apps/docker
ExecStart=/usr/bin/docker --graph /apps/docker
#配置 Docker 参数和镜像加速器
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://dockerhub.azk8s.cn",
"http://hub-mirror.c.163.com",
"https://registry.docker-cn.com"
],
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file":"5"
}
}
EOF
#启动 Docker:
$ systemctl start docker && systemctl enable docker

安装 kubelet、kubectl、kubeadm(全部节点)

  • kubelet: 在集群中的每个节点上用来启动 pod 和 container 等。
  • kubectl: 用来与集群通信的命令行工具。
  • kubeadm: 用来初始化集群的指令。
  • 注:安装顺序,一定不要先安装 kubeadm,因为 kubeadm 会自动安装最新版本的 kubelet 与 kubectl,导致版本不一致问题。
#创建repo仓库文件
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

#安装 kubelet
yum install -y kubelet-1.16.3-0

#安装 kubectl
yum install -y kubectl-1.16.3-0

#安装 kubeadm
yum install -y kubeadm-1.16.3-0

#启动 kubelet 并配置开机启动
systemctl start kubelet && systemctl enable kubelet

#重启全部节点
reboot

kubeadm 安装 kubernetes(Master 节点)

创建 kubeadm 配置文件 kubeadm-config.yaml,然后需要配置一些参数:

  • 配置 localAPIEndpoint.advertiseAddress 参数,调整为你的 Master 服务器地址。
  • 配置 imageRepository 参数,调整 kubernetes 镜像下载地址为阿里云。
  • 配置 networking.podSubnet 参数,调整为你要设置的网络范围。

kubeadm-config.yaml

apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 10.0.0.50
  bindPort: 6443
nodeRegistration:
  taints:
  - effect: PreferNoSchedule
    key: node-role.kubernetes.io/master
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
imageRepository: registry.aliyuncs.com/google_containers
kubernetesVersion: v1.16.3
networking:
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs

EOF

kubeadm 初始化 kubernetes 集群:

kubeadm init --config kubeadm-config.yaml

部署日志信息:

k8s三master架构 k8s架构原理_k8s三master架构_05

在此处看日志可以知道,可以通过下面命令,添加 kubernetes 相关环境变量:

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

部署 Calico 网络插件

下载 Calico 部署文件,并替换里面的网络范围为上面 kubeadm 中 networking.podSubnet 配置的值。

#下载 calico 部署文件
$ wget https://docs.projectcalico.org/v3.10/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml

#替换 calico 部署文件的 IP 为 kubeadm 中的 networking.podSubnet 参数 10.244.0.0。
sed -i 's/192.168.0.0/10.244.0.0/g' calico.yaml

#部署 Calico 插件
kubectl apply -f calico.yaml

#查看是否部署成功
kubectl get pod -n kube-system

工作节点加入集群(Work Node 节点)

根据上面 Master 节点创建 Kubernetes 集群时的日志信息,可以知道在各个节点上执行下面命令来让 工作节点加入主节点:

$ kubeadm join 192.168.2.11:6443 --token 4udy8a.f77ai0zun477kx0p \
--discovery-token-ca-cert-hash
sha256:4645472f24b438e0ecf5964b6dcd64913f68e0f9f7458768cfb96a9ab16b4212

如果上面 token 过期,则可以通过 kubeadm token create --print-join-command 命令重新获取加入 集群的指令。

配置 Kubectl 命令自动补全(Master 节点)

安装补全工具:

yum install -y bash-completion

添加补全配置:

source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

添加完成就可与通过输入 kubectl 后,按补全键(一般为 tab)会自动补全对应的命令。

k8s的组件部署以及使用

1.基本概念

k8s三master架构 k8s架构原理_docker_06

Ingress
其中,Ingress资源通过yaml文件申明规则配置

Ingress Controller
Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,以Pod的形式运行, 监控apiserver的/ingress端口后的backend services,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将 请求转发到对应的 Service。
核心是一个deployment,实现方式有很多,比如nginx, Contour, Haproxy, trafik, Istio,需要编写的 yaml有:Deployment, Service, ConfigMap, ServiceAccount(Auth),其中service的类型可以是 NodePort或者LoadBalancer。

组件部署

为了让Ingress Controller正常启动,需要给它配置一个默认的backend,用于当客户端访问的URL地址 不存在时,能够返回一个正确的404应答。 这个backend服务用任何应用实现都可以,只要满足默认对路径的访问返回404应答,并且提供/healthz完成对它的健康检查。如下,default-backend.yaml 文件可以在 官方 Ingress 仓库 找到

apiVersion: apps/v1
kind: Deployment
metadata:
  name: default-http-backend
  labels:
    app: default-http-backend
  namespace: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: default-http-backend
  template:
    metadata:
      labels:
        app: default-http-backend
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: default-http-backend
        # Any image is permissible as long as:
        # 1. It serves a 404 page at /
        # 2. It serves 200 on a /healthz endpoint
        image: registry.cn-hangzhou.aliyuncs.com/google_containers/defaultbackend:1.4
#        image: gcr.io/google_containers/defaultbackend:1.4
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi
---
 
apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: ingress-nginx
  labels:
    app: default-http-backend
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: default-http-backend

创建backend

kubectl apply -f default-backend.yaml

下载deploy.yaml

#访问网站下载文件
https://github.com/kubernetes/ingress-nginx/blob/controller-v0.48.1/deploy/static/provider/baremetal/deploy.yaml
#部署ingress-nginx
kubectl apply -f deploy.yaml

看看pod是否正常启动

kubectl get pods -n ingress-nginx

创建ingress

#ingress_test.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-test
  annotations:
    kubernetes.io/ingress.class: "nginx"
    # 开启use-regex,启用path的正则匹配
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
    # 定义域名
    - host: test.ingress.com
      http:
        paths:
        # 不同path转发到不同端口
          - path: /
            backend:
              serviceName: nginx-controller
              servicePort: 8000

创建ingress

kubectl apply -f ingress_test.yaml

创建nginx软件服务

vim nginx-rc.yaml
apiVersion: v1
kind: Deployment
metadata:
  name: nginx-controller
spec:
  replicas: 2
  selector:
    name: nginx
  template:
    metadata:
    labels:
    name: nginx
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
        - containerPort: 80
cat nginx-server-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service-nodeport
spec:
  ports:
  - port: 8000
  targetPort: 80
  protocol: TCP
type: NodePort
  selector:
    name: nginx
    
#创建pod以及service
kubectl apply -f nginx-rc.yaml
kubectl apply -f nginx-server-nodeport.yaml

通过curl访问对应nginx

curl -i test.ingress.com
HTTP/1.1 200 OK