简单入门Kubernetes

什么是Kubernetes

  • 官网

https://kubernetes.io/

中文版:https://kubernetes.io/zh/

image-20191203155553918

  • 个人理解
    • 基于容器技术
    • 分布式架构
    • 弹性伸缩
    • 隔离物理机
    • 和谷歌的Borg有关系
    • 用于部署、管理、运维我们的应用

Kubernetes核心概念

Kubernetes中的大部分概念,如:Node、Pod、Replication Controller、Service,都可以被视作一种资源对象。几乎所有的资源对象都可以通过Kubernetes提供的kubectl工具执行CRUD,并将其保存在etcd中进行持久化存储。

从这个角度看,Kubernetes是一个高度自动化的资源控制系统

它通过比较etcd中保存的资源期望值与当前环境的实际资源状态之间的差异,实现自动控制和自动纠错的高级功能

image-20191203142830394

Service

  • 拥有唯一的名称
  • 拥有一个虚拟IP和端口号
  • 能够提供某种远程服务能力
  • 被映射到提供这种服务能力的一组容器应用上

Node

  • 物理机
  • 云上的虚拟机

反正就是一台机器就对了

通常一个节点运行几百个Pod

Replication Controller

副本集

它能够保证Pod持续运行,并且在任何时候都有指定数量的Pod副本,在此基础上提供一些高级特性,比如滚动升级和弹性伸缩

image-20191203171838235

RC会在每个节点上创建Pod,Pod上如果有相应的Images可以直接创建,如果没有,则会拉取这个镜像再进行创建

在Kubernetes集群中,只要为需要扩容的Service关联到Pod创建的一个RC,服务扩容和升级就会变得非常简单

  • 一个RC文件,包含以下三个关键信息
    • 目标Pod的定义
    • 目标Pod需要运行的副本数量
    • 要监控的目标Pod的标签
  • 删除RC,并不会删除通过该RC创建好的Pod
    • 如果要删除RC对于的Pod,可以设置replicas值为0,然后更新RC
    • kubectl提供stop、delete命令,来一次性删除RC及其对应的Pod
  • 在应用升级的时候
    • 其实就是一个新的容器镜像替代旧版本的过程
    • 通过改变RC中Pod模板的镜像版本,实现滚动升级

ReplicaSet

Replica Set是Replication Controller的下一代

当前唯一的区别就是RS支持基于集合的Label Selector

image-20191204192025741

我们很少单独设置RS,主要是被Deployment这个更高层的资源对象所使用

从而形成一整套Pod创建、删除、更新的编排机制

Replica Set和Deployment这两个重要的资源对象,主键替代了RC的作用

Deployment

为了更好的解决Pod的编排问题,Deployment内部使用Replica Set

我们把Deployment当做一次RC的升级即可

image-20191204192447038

image-20191204192459539

image-20191204192531881

Pod

image-20191204181720871

Pod是Kubernetes管理的最小运行单元

一个Pod规定了其能够使用的硬件资源,达到隔离的作用

Pod内运行一个特殊的Container---Pause,在Pod内的其他Container,共享Pause的网络栈和Volume挂载卷

  • Pause
    • 用pause这个不易死亡的容器代表pod的存活与否
    • pod内的多个业务容器共享Pause的IP,共享Pause挂载的Volume
  • Kubernetes为每个Pod都分配了唯一IP--->Pod IP
  • 一个Pod内的多个容器共享Pod IP
  • 一个Pod内的容器与另外Node上的Pod容器可以直接通信

Container

镜像启动后,就是Container

Container运行在Pod中,多个紧密相关联的Container,我们一般会让他们运行在同一个Pod

Label

Kubernetes中的各个对象,都可以打上Label标签

标签是name=mysql这样子的键值对

一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上

Kubernetes架构设计

image-20191203170709992

Master

  • Master是集群控制节点
  • 负责运行管理相关的进程
  • 通常Master单独占用一个服务器,如果需要高可用,建议部署3台服务器
  • Master上运行着以下核心进程
    • Kubernetes API Server:kube-apiserver,集群控制入口
    • Kubernetes Controller Manager:kube-controller-manager,资源对象管理
    • Kubernetes Scheduler:kube-scheduler,资源调度
  • Master上通常还部署etcd服务,因为Kubernetes里的所有资源对象数据都保存在etcd中

Node

  • 工作节点,运行应用程序
  • Node上运行着以下核心进程
    • kubelet:负责Pod对应容器的创建、启停,与Master的协作,实现集群管理
    • kube-proxy:实现Kubernetes Service的通信,负载均衡的重要组件
    • docker
  • Node可以在Kubernetes运行期间动态加入集群
    • 前提是Node节点已经安装好了上述核心进程
    • 默认情况下,kubelet会向Master注册自己
  • 如果某个Node失联,Master会触发“工作负载大转移”的自动流程

HelloWorld

Kubernetes的安装先不讲了

  • 现在要做的事情是
    • 使用Kubernetes部署MySQL与JavaWeb程序
    • JavaWeb可以访问Kubernetes
  • 基本步骤
    • MySQL副本集
    • MySQL Service
    • JavaWeb副本集
    • JavaWeb Service

MySQL RC

  • mysql-rc.yaml
apiVersion: v1
# 表名这是一个副本集
kind: ReplicationController
metadata:
# RC的名称,全局唯一
  name: mysql
spec:
# 期待的Pod数量
  replicas: 1
  selector:
    app: mysql
# 根据此模板创建Pod副本
  template:
    metadata:
      labels:
# Pod副本拥有的标签,对应RC的Selector      
        app: mysql
    spec:
      containers:
      - name: mysql
        image: registry.cn-hangzhou.aliyuncs.com/sherry/mysql:5.7
        ports:
# 容器应用监听的端口号        
        - containerPort: 3306
# 注入容器内的环境变量        
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"复制代码

注意这里的yaml文件,不可以有制表符,我们一律使用空格键代替

编写完文件后,使用apply命令做个文件格式检查

➜  k8s git:(master) ✗ kubectl apply -f mysql-rc.yaml
replicationcontroller/mysql created复制代码

  • 创建RC
➜  k8s git:(master) ✗ kubectl create -f mysql-rc.yaml
replicationcontroller/mysql created复制代码

  • 查看创建结果
➜  k8s git:(master) ✗ kubectl get rc
NAME    DESIRED   CURRENT   READY   AGE
mysql   1         1         1       4m17s复制代码

  • 查看创建的Pod情况
➜  k8s git:(master) ✗ kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
mysql-wg9sp   1/1     Running   0          5m16s复制代码

  • dashboard

其实通过dashboard,也能看到启动情况

image-20191204124739155

MySQL Service

  • mysql-svc.yaml
apiVersion: v1
kind: Service           # 表名这是一个Kubernetes Service
metadata:
  name: mysql           # Service全局名称
spec:
  ports:
    - port: 3306        # Service对外提供的端口
  selector:
    app: mysql          # Service对应的Pod拥有此标签,所有拥有此标签的pod都归我管复制代码

  • 创建Service
➜  k8s git:(master) ✗ kubectl create -f mysql-svc.yaml
service/mysql created复制代码

  • 查看创建结果
➜  k8s git:(master) ✗ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    175m
mysql        ClusterIP   10.105.55.185   <none>        3306/TCP   84s复制代码

可以发现,MySQL服务被分配了一个值为10.105.55.185CLUSTER-IP,端口为3306

此时,Kubernetes集群中其他创建的Pod就可以通过这个ip+端口进行连接和访问了

这里的ip,是Service创建后由Kubernetes系统自动分配的,

其他Pod无法余弦知道,所以需要有一个服务发现机制来找到这个服务。

现在,我们根据Service的唯一名称获取到ip和端口

JavaWeb RC

  • myweb-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 2
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
        - name: myweb
          image: kubeguide/tomcat-app:v1
          ports:
          - containerPort: 8080复制代码

在Tomcat容器内部,应用将使用环境变量MYSQLSERVICEHOST的值连接MySQL,更安全的做法是使用服务的名称mysql进行访问

  • 创建RC
➜  k8s git:(master) ✗ kubectl create -f myweb-rc.yaml
replicationcontroller/myweb created复制代码

  • 验证
➜  k8s git:(master) ✗ kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
mysql-ck4j5   1/1     Running   0          164m
myweb-8dhr9   1/1     Running   0          3m11s
myweb-nm75w   1/1     Running   0          3m11s复制代码

JavaWeb Service

  • myweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  type: NodePort
  ports:
    - port: 8080
      nodePort: 30001
  selector:
    app: myweb复制代码

type: NodePortnodePort: 30001,表明此Service开启了NodePort方式的外网访问模式

  • 启动
➜  k8s git:(master) ✗ kubectl create -f myweb-svc.yaml 
service/myweb created复制代码

  • 验证
➜  k8s git:(master) ✗ kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP          5h47m
mysql        ClusterIP   10.105.55.185   <none>        3306/TCP         174m
myweb        NodePort    10.101.31.133   <none>        8080:30001/TCP   41s复制代码

验证

经过上述步骤,我们通过dashbaord看看到底启动了哪些服务

  • Service

image-20191204155811477

  • RC

image-20191204155830187

  • Pod

image-20191204155844792

我们可以使用 http://虚拟机ip:30001/demo/ 的方式来进行验证访问

那么怎么获取这个虚拟机的ip呢?

我这里使用的是minikube安装的Kubernetes环境,安装后,在虚拟机中的Linux,账号是root,密码为空

然后使用ipconfig|more命令就能看到ip

image-20191204172927321

ok,至此,我们的hello world完毕

如何声明Kubernetes资源对象

在hello world中,我们已经使用yaml格式的方式,声明了RC和Service两种资源对象

其实还可以是JSON格式(不常用)

基础

下面我们具体讲讲每一个配置

# 声明需要用到的api版本
#Kubernetes平台采用的是核心+外围扩展的设计思路
#常见的核心资源对象都归属于v1这个核心api
apiVersion: v1
# 表名这是一个副本集,还可以是 Pod、Service等
kind: ReplicationController
metadata:
# RC的名称,全局唯一
  name: mysql
  labels:
      name: XXX # 定义了一个标签,name=XXX
# 定义容器组      
spec:
# 期待的Pod数量
  replicas: 1
# selector是标签选择器,这里表示,当前容器组处理拥有app=mysql标签的Pod  
  selector:
    app: mysql
# 根据此模板创建Pod副本
  template:
    metadata:
      labels:
# Pod副本拥有的标签,对应RC的Selector      
        app: mysql
# 定义容器组        
    spec:
      containers:
      - name: mysql
        image: registry.cn-hangzhou.aliyuncs.com/sherry/mysql:5.7
        resources:
# 设置一个较小的值,符合容器平时工作负载下的资源需求        
            requests:
# 内存占用,默认单位为字节,一般我们使用Mi,表示兆            
                memory: "64Mi"
# 以1/1000为最小单位,100m表示0.1个CPU
# 不管是在一个1Core的机器还是8Core的机器上,100m代表的含义都是一样的
                cpu: "250m"
# 设置一个较大的值,符合容器峰值负载下的资源需求                
# 当容器试图使用超过这个量的资源时,可能被Kubernetes杀掉并重启
            limits:
                memory: "128Mi"
                cpu: "500m"
        ports:
# 容器应用监听的端口号,PodIP+这个端口,组成了新的概念:Endpoint
# 代表此Pod里的一个服务进程的对外通信地址
        - containerPort: 3306
# 注入容器内的环境变量        
        env:
        - name: MYSQL_SERVICE_HOST
            value: "mysql"
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"复制代码

Selector表达式

image-20191204190825504

kubectl命令详解

详细命令的使用,通过kubectl help获得

查看

  • 查看Node
➜  k8s git:(master) ✗ kubectl get nodes
NAME       STATUS   ROLES    AGE   VERSION
minikube   Ready    master   8h    v1.16.2复制代码

  • 查看某个node详情

这里的minikube是node的name

➜  k8s git:(master) ✗ kubectl describe node minikube
Name:               minikube
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=minikube
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
Annotations:        kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Wed, 04 Dec 2019 10:02:05 +0800
Taints:             <none>
Unschedulable:      false
Conditions:
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  MemoryPressure   False   Wed, 04 Dec 2019 18:12:44 +0800   Wed, 04 Dec 2019 10:02:01 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available
  DiskPressure     False   Wed, 04 Dec 2019 18:12:44 +0800   Wed, 04 Dec 2019 10:02:01 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure
  PIDPressure      False   Wed, 04 Dec 2019 18:12:44 +0800   Wed, 04 Dec 2019 10:02:01 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available
  Ready            True    Wed, 04 Dec 2019 18:12:44 +0800   Wed, 04 Dec 2019 10:02:01 +0800   KubeletReady                 kubelet is posting ready status
Addresses:
  InternalIP:  192.168.99.105复制代码

本文由博客一文多发平台 OpenWrite 发布!

猜你喜欢

转载自juejin.im/post/5de79b23f265da33d83e58e3