云原生入门实战

参考文档
https://www.yuque.com/leifengyang/oncloud/ctiwgo

基础概念

公有云、私有云概念、混合云

云平台实战

开通阿里云ECS(按量计费)

在这里插入图片描述

配置访问工具

electermhttps://electerm.github.io/electerm/
https://wwa.lanzoui.com/b016k9bha
密码:900h

安装Nginx

# 安装
yum install nginx
# 启动
systemctl start nginx

安装完成以后验证,浏览器输入实例的公网IP地址

实例安全组配置


如图,实例在设置安全组以后,可以按需配置安全组相关设置。

私有网络VPC实战

VPC:私有网络、专有网络
云服务器集群各机器之间,一般使用私有IP访问。私有IP不占用公网IP流量,不同VPC网络下服务器之间互相隔离。同一VPC网络下,服务器互相连通。
在这里插入图片描述
在这里插入图片描述
如图所示,两个挂载在同一专用网络下的服务器,可以使用私有IP互相ping通

容器化基础

Docker基础

虚拟化技术

云原生入门实战_第1张图片

容器化技术

云原生入门实战_第2张图片

Docker基本概念

解决的问题

  1. 统一标准
    应用构建:不同软件的打包、编译、安装、docker build
    应用分享:docker hub
    应用运行:统一标准的镜像、docker run
  2. 资源的隔离
    CPU、内存资源的隔离与限制
    访问设备的隔离与限制
    网络隔离与限制
    用户、用户组隔离与限制

架构

云原生入门实战_第3张图片

  1. Docker Host:安装Docker的主机
  2. Docker Daemon:运行在Docker主机上的后台Docker进程
  3. Client:操作Docker主机的客户端:命令行/UI等
  4. Registry:镜像仓库、Docker Hub
  5. Images:镜像,带环境打包好的程序,可以直接运行
  6. Containers:由镜像启动起来的正在运行的程序

Docker实战

安装

各系统下的安装参考

  1. 移除之前的docker相关包(如有)

    sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
    
  2. 配置yum源

    sudo yum install -y yum-utils
    sudo yum-config-manager --add-repo \
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
  3. 安装Docker

    sudo yum install -y docker-ce docker-ce-cli containerd.io
    #以下是在安装k8s的时候使用
    yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7  containerd.io-1.4.6
    
  4. 启动

    systemctl enable docker --now
    
  5. 配置加速器
    阿里云提供了免费的镜像加速器

    sudo mkdir -p /etc/docker
    sudo tee /etc/docker/daemon.json <<-'EOF'
    {
      "registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
        "max-size": "100m"
      },
      "storage-driver": "overlay2"
    }
    EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    
  6. 检查docker运行状态

    docker ps
    

    如果正确安装,控制台会输出如下内容。 在这里插入图片描述

实战

基础实战

  1. 镜像下载:docker hub
    以Nginx为例:
    云原生入门实战_第4张图片

    # 下载最新版
    docker pull nginx
    # 下载指定版本
    docker pull nginx:1.20.1
    # 查看已经下载的镜像
    docker images 
    # 移除镜像 镜像名:版本号/镜像id
    docker rmi nginx:latest
    
  2. 启动容器

    # -d:后台运行
    # --restart=always: 开机自启
    # 88:80 这是端口映射操作,规则 主机端口:容器端口
    docker run --name=mynginx   -d  --restart=always -p  88:80   nginx
    # 查看正在运行的容器
    docker ps
    # 查看所有
    docker ps -a
    # 删除停止的容器
    docker rm  容器id/名字
    #强制删除正在运行中的
    docker rm -f mynginx   
    #停止容器
    docker stop 容器id/名字
    #再次启动
    docker start 容器id/名字
    #应用开机自启
    docker update 容器id/名字 --restart=always
    
  3. 修改容器内容
    进入容器内修改

    # 进入容器内部的系统,修改容器内容
    # dc4254016fe9:对应的容器ID,可在docker ps查看
    docker exec -it dc4254016fe9  /bin/bash
    


    修改完成以后,可以通过服务器的公网Ip:88方式访问,会发现写入的内容展现在页面。
    通过外部挂载的方式修改

    # -v 主机目录:容器目录:ro/rw表示操作权限
    docker run --name=mynginx -d  --restart=always -p  88:80 -v /data/html:/usr/share/nginx/html:ro	nginx
    # 挂载完成以后,就可以去主机的/data/html修改对应页面
    
  4. 提交容器的修改

    # docker commit [OPTIONS] CONTAINER:容器ID [REPOSITORY[:TAG]]:镜像版本
    docker commit -a "satoshi" -m "更新nginx首页" dc4254016fe9 mynginx:v1.0
    

    提交以后可以通过命令查看,发现会有新的镜像出现。
    在这里插入图片描述

  5. 镜像传输

    # 将镜像保存成压缩包
    docker save -o abc.tar mynginx:v1.0
    
    # 别的机器加载这个镜像
    docker load -i abc.tar
    
  6. 推送镜像到远端仓库

    # 把旧镜像的名字,改成仓库要求的新版名字
    docker tag mynginx:v1.0 satoshi/mynginx:v1.0
    # 推送
    docker push satoshi/mynginx:v1.0
    # 登录到docker hub
    docker login 
    # 推送完成镜像后退出      
    docker logout
    # 别的机器下载
    docker pull satoshi/mynginx:v1.0
    
  7. 补充

    docker logs 容器名/id   排错
    docker exec -it 容器id /bin/bash
    # docker 经常修改nginx配置文件
    docker run -d -p 80:80 \
    -v /data/html:/usr/share/nginx/html:ro \
    -v /data/conf/nginx.conf:/etc/nginx/nginx.conf \
    --name mynginx-02 \
    nginx
    #把容器指定位置的东西复制出来 
    docker cp 5eff66eec7e1:/etc/nginx/nginx.conf  /data/conf/nginx.conf
    #把外面的内容复制到容器里面
    docker cp  /data/conf/nginx.conf  5eff66eec7e1:/etc/nginx/nginx.conf
    

进阶实战

以Java应用为例,创建自定义APP的镜像并发布。

  1. 安装Redis镜像
    # 下载
    docker pull redis
    # 创建redis配置文件/data/redis/redis.conf,配置密码和开启AOF
    # 创建redis数据文件夹/data/redis/data
    # 启动redis容器
    docker run -v /data/redis/redis.conf:/etc/redis/redis.conf \
    -v /data/redis/data:/data \
    -d --name myredis \
    -p 6379:6379 \
    redis:latest  redis-server /etc/redis/redis.conf
    
  2. 创建一个简单的Spring Boot项目
    // 用于访问Redis服务,记录接口的访问次数
    @RestController
    public class CountController {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @GetMapping("/hello")
        public String hello(){
            BoundValueOperations<String, String> stringStringBoundValueOperations = stringRedisTemplate.boundValueOps("visit-count");
            Long increment = stringStringBoundValueOperations.increment();
            return "【"+ increment +"】次访问";
        }
    }
    
    # 配置redis参数
    spring.redis.host=47.116.88.143
    spring.redis.port=6379
    spring.redis.password=qwe123456
    
  3. 编写DockerFile
    # 构件java应用所需要的环境依赖-JDK,对应的image和tag可以在docker hub找到
    FROM openjdk:8-jdk-slim
    # maintainer标识作者
    LABEL maintainer=satoshi
    # copy命令标识在docker build的时候,需要将当前目录下target文件夹内的jar包复制到容器指定路径下
    COPY target/*.jar   /app.jar
    # 这句标识启动该应用所需的命令(即运行jar包的命令)
    ENTRYPOINT ["java","-jar","/app.jar"]
    
  4. 将对应的jar包和DockerFile文件上传到Docker服务器
    云原生入门实战_第5张图片
  5. 上传完成以后执行docker build命令
    # 命令尾部的 . 指定执行时的当前目录
    # java-demo 镜像名
    # v1.0 tag
    docker build -t java-demo:v1.0 .
    
    执行结果云原生入门实战_第6张图片
    ducker images查看构建结果云原生入门实战_第7张图片
  6. 启动自定义的镜像
    docker run -d -p 8080:8080 --name myjava-app java-demo:v1.0 
    
    页面验证结果
    云原生入门实战_第8张图片

Kubernetes基础

k8s基本概念

是什么

k8s出现的背景

官方文档

传统部署时代:

早期,各机构是在物理服务器上运行应用程序。 由于无法限制在物理服务器中运行的应用程序资源使用,因此会导致资源分配问题。
例如,如果在物理服务器上运行多个应用程序, 则可能会出现一个应用程序占用大部分资源的情况,而导致其他应用程序的性能下降。
一种解决方案是将每个应用程序都运行在不同的物理服务器上, 但是当某个应用程式资源利用率不高时,剩余资源无法被分配给其他应用程式,
而且维护许多物理服务器的成本很高。

虚拟化部署时代:

因此,虚拟化技术被引入了。虚拟化技术允许你在单个物理服务器的 CPU 上运行多台虚拟机(VM)。 虚拟化能使应用程序在不同 VM之间被彼此隔离,且能提供一定程度的安全性, 因为一个应用程序的信息不能被另一应用程序随意访问。

虚拟化技术能够更好地利用物理服务器的资源,并且因为可轻松地添加或更新应用程序, 而因此可以具有更高的可伸缩性,以及降低硬件成本等等的好处。

每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统(OS)。

容器部署时代:

容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。 因此,容器比起 VM 被认为是更轻量级的。且与 VM类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。

容器因具有许多优势而变得流行起来。
下面列出的是容器的一些好处:

敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性), 提供可靠且频繁的容器镜像构建和部署。
关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。 可观察性:不仅可以显示 OS级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。 跨云和操作系统发行版本的可移植性:可在Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
资源隔离:可预测的应用程序性能。 资源利用:高效率和高密度。

云原生入门实战_第9张图片

k8s的功能

容器是打包和运行应用程序的好方式。在生产环境中, 你需要管理运行着应用程序的容器,并确保服务不会下线。 例如,如果一个容器发生故障,则你需要启动另一个容器。 如果此行为交由给系统处理,是不是会更容易一些?

这就是 Kubernetes 要来做的事情! Kubernetes 为你提供了一个可弹性运行分布式系统的框架。 Kubernetes 会满足你的扩展要求、故障转移、部署模式等。 例如,Kubernetes 可以轻松管理系统的灰度部署。

Kubernetes 为你提供:

  1. 服务发现和负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址来曝露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  2. 存储编排

    Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。

  3. 自动部署和回滚

    你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

  4. 自动完成装箱计算

    Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来为容器分配资源。

  5. 自我修复

    Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。

  6. 密钥与配置管理

    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

k8s架构

工作模式

N master节点+ N worker节点,N>=1

组件架构

云原生入门实战_第10张图片

  1. 集群交互:API Server
  2. 集群控制器:Control manager
  3. 新建任务调度器:Scheduler
  4. 集群后台键值数据库:ETCD
  5. 云提供商控制器:Cloud Control Manager
  6. 集群网络访问代理:Kube-proxy
  7. 容器生命周期管理和监控:Kubelet

kubernetes安装

申请三台云服务器(2核4G)、分配公网IP,并加入一个VPC。
云原生入门实战_第11张图片

安装docker

参考前面章节docker实战的docker安装

安装kubelet、kubeadm、kubectl

  1. 环境要求
    ● 一台兼容的 Linux 主机。Kubernetes 项目为基于 Debian 和 Red Hat 的 Linux 发行版以及一些不提供包管理器的发行版提供通用的指令
    ● 每台机器 2 GB 或更多的 RAM (如果少于这个数字将会影响你应用的运行内存) 2 CPU 核或更多
    ● 集群中的所有机器的网络彼此均能相互连接(公网和内网都可以)
    ● 节点之中不可以有重复的主机名、MAC 地址或 product_uuid。
    ● 开启机器上的某些端口。VPC组内互通
    ● 禁用交换分区。为了保证 kubelet 正常工作,你 必须 禁用交换分区。

  2. 基础操作

    #各个机器设置自己的域名
    hostnamectl set-hostname xxxx
    # 将 SELinux 设置为 permissive 模式(相当于将其禁用)
    sudo setenforce 0
    sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
    #关闭swap
    swapoff -a  
    sed -ri 's/.*swap.*/#&/' /etc/fstab
    #允许 iptables 检查桥接流量
    cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    br_netfilter
    EOF
    cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF
    sudo sysctl --system
    
  3. 安装kubelet、kubeadm、kubectl

    cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
    enabled=1
    gpgcheck=0
    repo_gpgcheck=0
    gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
    exclude=kubelet kubeadm kubectl
    EOF
    
    
    sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
    
    sudo systemctl enable --now kubelet
    

    kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环

使用kubeadm引导集群

  1. 下载所需要的镜像

    sudo tee ./images.sh <<-'EOF'
    #!/bin/bash
    images=(
    kube-apiserver:v1.20.9
    kube-proxy:v1.20.9
    kube-controller-manager:v1.20.9
    kube-scheduler:v1.20.9
    coredns:1.7.0
    etcd:3.4.13-0
    pause:3.2
    )
    for imageName in ${images[@]} ; do
    docker pull registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/$imageName
    done
    EOF
    
    chmod +x ./images.sh && ./images.sh
    
  2. 初始化主节点

    #所有机器添加master域名映射,以下需要修改为自己的
    echo "你的节点内网IP  cluster-endpoint" >> /etc/hosts
    #主节点初始化
    kubeadm init \
    --apiserver-advertise-address=192.168.40.3 \
    --control-plane-endpoint=cluster-endpoint \
    --image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
    --kubernetes-version v1.20.9 \
    --service-cidr=10.96.0.0/16 \
    --pod-network-cidr=172.31.0.0/16
    #配置要求:你的服务器内网IP网段、service-cidr、pod-network-cidr网络范围不重叠
    
  3. 执行结果
    云原生入门实战_第12张图片

  4. 按照命令指示完成后续步骤

    Your Kubernetes control-plane has initialized successfully!
    
    To start using your cluster, you need to run the following as a regular user:
    # 这里是后续步骤一:
    
      mkdir -p $HOME/.kube
      sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      sudo chown $(id -u):$(id -g) $HOME/.kube/config
    
    Alternatively, if you are the root user, you can run:
    
      export KUBECONFIG=/etc/kubernetes/admin.conf
    
    # 后续步骤二:配置pod 网络。这里选用calico
    # calico
    # curl https://docs.projectcalico.org/manifests/calico.yaml -O
    # 注意,上面配置的--pod-network-cidr=172.31.0.0/16需要与calico.yaml 里面的CALICO_IPV4POOL_CIDR的value保持一致
    # kubectl apply -f calico.yaml
    You should now deploy a pod network to the cluster.
    Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
      https://kubernetes.io/docs/concepts/cluster-administration/addons/
    
    
    You can now join any number of control-plane nodes by copying certificate authorities
    and service account keys on each node and then running the following as root:
    # 后续步骤三:新的master节点加入k8s集群的方式
    
      kubeadm join cluster-endpoint:6443 --token 6fd3kz.9wkpm4niy7euflzs \
        --discovery-token-ca-cert-hash sha256:a5a159eb8504012c4caa7cfefe86964cca80a36d580ab6392db9ddcdbc9f293f \
        --control-plane 
    
    Then you can join any number of worker nodes by running the following on each as root:
    # 后续步骤三 新的worker节点加入集群的方式
    kubeadm join cluster-endpoint:6443 --token 6fd3kz.9wkpm4niy7euflzs \
        --discovery-token-ca-cert-hash sha256:a5a159eb8504012c4caa7cfefe86964cca80a36d580ab6392db9ddcdbc9f293f
    
    #查看集群所有节点
    kubectl get nodes
    
    #根据配置文件,给集群创建资源
    kubectl apply -f xxxx.yaml
    
    #查看集群部署了哪些应用?
    docker ps   ===   kubectl get pods -A
    # 运行中的应用在docker里面叫容器,在k8s里面叫Pod
    kubectl get pods -A
    
  5. 安装完成以后验证集群状态
    在这里插入图片描述
    云原生入门实战_第13张图片

  6. 安装dashboard
    kubernetes官方提供的可视化界面
    部署

    kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
    

    如果下载失败,可以直接使用以下的yml文件

    # Copyright 2017 The Kubernetes Authors.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Namespace
    metadata:
      name: kubernetes-dashboard
    
    ---
    
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    
    ---
    
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    spec:
      ports:
        - port: 443
          targetPort: 8443
      selector:
        k8s-app: kubernetes-dashboard
    
    ---
    
    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard-certs
      namespace: kubernetes-dashboard
    type: Opaque
    
    ---
    
    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard-csrf
      namespace: kubernetes-dashboard
    type: Opaque
    data:
      csrf: ""
    
    ---
    
    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard-key-holder
      namespace: kubernetes-dashboard
    type: Opaque
    
    ---
    
    kind: ConfigMap
    apiVersion: v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard-settings
      namespace: kubernetes-dashboard
    
    ---
    
    kind: Role
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    rules:
      # Allow Dashboard to get, update and delete Dashboard exclusive secrets.
      - apiGroups: [""]
        resources: ["secrets"]
        resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
        verbs: ["get", "update", "delete"]
        # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
      - apiGroups: [""]
        resources: ["configmaps"]
        resourceNames: ["kubernetes-dashboard-settings"]
        verbs: ["get", "update"]
        # Allow Dashboard to get metrics.
      - apiGroups: [""]
        resources: ["services"]
        resourceNames: ["heapster", "dashboard-metrics-scraper"]
        verbs: ["proxy"]
      - apiGroups: [""]
        resources: ["services/proxy"]
        resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
        verbs: ["get"]
    
    ---
    
    kind: ClusterRole
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
    rules:
      # Allow Metrics Scraper to get metrics from the Metrics server
      - apiGroups: ["metrics.k8s.io"]
        resources: ["pods", "nodes"]
        verbs: ["get", "list", "watch"]
    
    ---
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: kubernetes-dashboard
    subjects:
      - kind: ServiceAccount
        name: kubernetes-dashboard
        namespace: kubernetes-dashboard
    
    ---
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: kubernetes-dashboard
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: kubernetes-dashboard
    subjects:
      - kind: ServiceAccount
        name: kubernetes-dashboard
        namespace: kubernetes-dashboard
    
    ---
    
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
      name: kubernetes-dashboard
      namespace: kubernetes-dashboard
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          k8s-app: kubernetes-dashboard
      template:
        metadata:
          labels:
            k8s-app: kubernetes-dashboard
        spec:
          containers:
            - name: kubernetes-dashboard
              image: kubernetesui/dashboard:v2.3.1
              imagePullPolicy: Always
              ports:
                - containerPort: 8443
                  protocol: TCP
              args:
                - --auto-generate-certificates
                - --namespace=kubernetes-dashboard
                # Uncomment the following line to manually specify Kubernetes API server Host
                # If not specified, Dashboard will attempt to auto discover the API server and connect
                # to it. Uncomment only if the default does not work.
                # - --apiserver-host=http://my-address:port
              volumeMounts:
                - name: kubernetes-dashboard-certs
                  mountPath: /certs
                  # Create on-disk volume to store exec logs
                - mountPath: /tmp
                  name: tmp-volume
              livenessProbe:
                httpGet:
                  scheme: HTTPS
                  path: /
                  port: 8443
                initialDelaySeconds: 30
                timeoutSeconds: 30
              securityContext:
                allowPrivilegeEscalation: false
                readOnlyRootFilesystem: true
                runAsUser: 1001
                runAsGroup: 2001
          volumes:
            - name: kubernetes-dashboard-certs
              secret:
                secretName: kubernetes-dashboard-certs
            - name: tmp-volume
              emptyDir: {}
          serviceAccountName: kubernetes-dashboard
          nodeSelector:
            "kubernetes.io/os": linux
          # Comment the following tolerations if Dashboard must not be deployed on master
          tolerations:
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
    
    ---
    
    kind: Service
    apiVersion: v1
    metadata:
      labels:
        k8s-app: dashboard-metrics-scraper
      name: dashboard-metrics-scraper
      namespace: kubernetes-dashboard
    spec:
      ports:
        - port: 8000
          targetPort: 8000
      selector:
        k8s-app: dashboard-metrics-scraper
    
    ---
    
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      labels:
        k8s-app: dashboard-metrics-scraper
      name: dashboard-metrics-scraper
      namespace: kubernetes-dashboard
    spec:
      replicas: 1
      revisionHistoryLimit: 10
      selector:
        matchLabels:
          k8s-app: dashboard-metrics-scraper
      template:
        metadata:
          labels:
            k8s-app: dashboard-metrics-scraper
          annotations:
            seccomp.security.alpha.kubernetes.io/pod: 'runtime/default'
        spec:
          containers:
            - name: dashboard-metrics-scraper
              image: kubernetesui/metrics-scraper:v1.0.6
              ports:
                - containerPort: 8000
                  protocol: TCP
              livenessProbe:
                httpGet:
                  scheme: HTTP
                  path: /
                  port: 8000
                initialDelaySeconds: 30
                timeoutSeconds: 30
              volumeMounts:
              - mountPath: /tmp
                name: tmp-volume
              securityContext:
                allowPrivilegeEscalation: false
                readOnlyRootFilesystem: true
                runAsUser: 1001
                runAsGroup: 2001
          serviceAccountName: kubernetes-dashboard
          nodeSelector:
            "kubernetes.io/os": linux
          # Comment the following tolerations if Dashboard must not be deployed on master
          tolerations:
            - key: node-role.kubernetes.io/master
              effect: NoSchedule
          volumes:
            - name: tmp-volume
              emptyDir: {}
    

    设置访问端口

    kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard
    # 进入编辑页面后,将type:ClusterIP改为NodePort
    

    查看端口,配置安全组

    kubectl get svc -A |grep kubernetes-dashboard
    # 根据按照下图,需要配置开放31242端口
    

    在这里插入图片描述
    创建访问账户

    #创建访问账号,准备一个yaml文件; vi dash-user.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: admin-user
      namespace: kubernetes-dashboard
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: admin-user
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: admin-user
      namespace: kubernetes-dashboard
    
    # 应用该文件
    kubectl apply -f dash-user.yaml
    

    获取访问令牌

    kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"
    
    # 这是Token
    eyJhbGciOiJSUzI1NiIsImtpZCI6IkZkZ0k5WFRWbXo2b0FMb3RSVGlJclM3RWtKZFpRbGtPNXc5LUk0c3dvOVkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi11c2VyLXRva2VuLTQ5N3RnIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImFkbWluLXVzZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiIzODI5ODUxYi0xOTJmLTQxMGMtYjU4YS00MmRmZjgzNWJhNzAiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZXJuZXRlcy1kYXNoYm9hcmQ6YWRtaW4tdXNlciJ9.G4W4TeCvI1g4r10WZhHMMuVeiTKeb0m3x5_kiAJfCz9EOKIcTXXKlUeQ1bjdPKNU9sXqmCg2vkQjkoFyMjHwok_zcEMV0DgraIdtrXWCiRZ3X0HY63O3kGmtVYlKwaqsIf7S65YlhOzN9cvRE1F8KS97XZDDvdnRagyB0wJ7u46r0TDDVxYfdHH-LkQn_9PGgn03Fou7keOWQDOYWypGFEHaKOjwsz-pKJEfTaT941QkWedXGr3ZX0zSX7t_6bq8AYlRXINWOU-fOr4fNOsfaZdG-zeSyaj4DfiXdDvLGazlT8Skz2j5iZXUgFzPgDPr58VXaaUOPQybVYzVI5JR2Q
    

    输入Token即可进入Dashboard
    云原生入门实战_第14张图片

k8s核心实战

资源创建方式

  1. 命令行
  2. YAML文件方式

Namespace

命名空间(Namespace)用于隔离资源,默认只隔离资源,不隔离网络。

  1. 命令行方式管理命名空间
    # 创建
    kubectl create ns hello
    # 删除
    kubectl delete ns hello 
    
  2. YAML方式创建命名空间
    apiVersion: v1
    kind: Namespace
    metadata:
    	name: hello
    
    # 通过配置文件创建
    kubectl apply -f hello.yaml
    # 通过配置文件删除
    kubectl delete -f hello.yaml
    

Pod

Pod标识一组运行中的容器,它是kubernetes中应用的最小单位。
不同Pod之间具有隔离性,同一个Pod内不同容器共享网络空间、存储、CPU等。
一个Pod内可运行多个应用(docker概念里面的多个容器)。
Pod名称不能重复。
云原生入门实战_第15张图片

# 命令行创建nginx pod
kubectl run mynginx --image=nginx

# 查看default名称空间的Pod
kubectl get pod 
# 描述
kubectl describe pod 你自己的Pod名字
# 删除
kubectl delete pod Pod名字
# 查看Pod的运行日志
kubectl logs Pod名字

# 每个Pod - k8s都会分配一个ip
kubectl get pod -owide
# 使用Pod的ip+pod里面运行容器的端口
curl 192.168.169.136
# 集群中的任意一个机器以及任意的应用都能通过Pod分配的ip来访问这个Pod
  • 以YAML方式创建Nginx Pod
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: mynginx
      name: mynginx
    #  namespace: default
    spec:
      containers:
      - image: nginx
        name: mynginx
    
  • 以YAML方式创建Nginx + Tomcat Pod
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
        run: myapp
      name: myapp
    spec:
      containers:
      - image: nginx
        name: nginx
      - image: tomcat:8.5.68
        name: tomcat
    
  • 通过YAML删除对应的Pod
    kubectl delete -f xxx.yaml
    
  • 通过Dashboard创建Pod
    云原生入门实战_第16张图片
    云原生入门实战_第17张图片
  • 通过Dashboard进入Pod命令行界面
    云原生入门实战_第18张图片
  • Pod界面一览
    云原生入门实战_第19张图片

Deployment

控制Pod,使Pod拥有多副本,自愈,扩缩容等能力。
通过deployment方式创建的pod具有自愈能力(pod宕机、被人为关闭等异常时,deployment会自动拉起新的pod)

kubectl create deployment mytomcat --image=tomcat:8.5.68
  1. 多副本
    命令行方式

    kubectl create deployment my-dep --image=nginx --replicas=3
    

    yaml方式

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: my-dep
      name: my-dep
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: my-dep
      template:
        metadata:
          labels:
            app: my-dep
        spec:
          containers:
          - image: nginx
            name: nginx
    

    在这里插入图片描述

  2. 扩缩容

    # 从2扩到5
    kubectl scale --replicas=5 deployment/my-dep
    # 直接修改deployment文件的参数也可以实现扩容/缩容
    kubectl edit deployment my-dep
    

    云原生入门实战_第20张图片

    # 从5缩到3
    kubectl scale --replicas=3 deployment/my-dep
    

    云原生入门实战_第21张图片
    在可视化界面实现扩缩容
    云原生入门实战_第22张图片

  3. 自愈、故障转移等
    停机、删除Pod、容易崩溃等场景下,实现副本保证。

  4. 滚动更新(不停机更新)

    kubectl set image deployment/my-dep nginx=nginx:1.16.1 --record
    # 下面是打印滚动更新的实时状态
    kubectl rollout status deployment/my-dep
    

    云原生入门实战_第23张图片
    滚动更新的操作,会逐个替换老的容器为新的容器,这个过程中如果新容器出现错误,则后续的更新不会继续。

  5. 版本回退

    #历史记录
    kubectl rollout history deployment/my-dep
    
    #查看某个历史详情
    kubectl rollout history deployment/my-dep --revision=2
    
    #回滚(回到上次)
    kubectl rollout undo deployment/my-dep
    
    #回滚(回到指定版本)
    kubectl rollout undo deployment/my-dep --to-revision=2
    
  6. 其他工作负载
    除了Deployment,k8s还有 StatefulSet 、DaemonSet 、Job 等 类型资源。我们都称为 工作负载。有状态应用使用 StatefulSet 部署,无状态应用使用 Deployment 部署。
    官方说明云原生入门实战_第24张图片

Service

Pod的服务发现与负载均衡

  1. 配置ClusterIP方式(只能集群内访问)
    yaml配置文件
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: my-dep
      name: my-dep
    spec:
      selector:
        app: my-dep
      ports:
      - port: 8000
        protocol: TCP
        targetPort: 80
    
    通过命令行
    # 等同于没有--type的
    kubectl expose deployment my-dep --port=8000 --target-port=80 --type=ClusterIP
    
  2. 配置NodePort方式(外网可以访问)
    yaml配置文件
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: my-dep
      name: my-dep
    spec:
      ports:
      - port: 8000
        protocol: TCP
        targetPort: 80
      selector:
        app: my-dep
      type: NodePort
    
    通过命令行方式
    kubectl expose deployment my-dep --port=8000 --target-port=80 --type=NodePort
    
  3. 查看创建的service
    kubectl get service
    

Ingress

安装

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.47.0/deploy/static/provider/baremetal/deploy.yaml

#修改镜像
vi deploy.yaml
#将image的值改为如下值:
registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/ingress-nginx-controller:v0.46.0

# 检查安装的结果
kubectl get pod,svc -n ingress-nginx

# 最后别忘记把svc暴露的端口要放行

使用

官方地址
测试环境

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-server
  template:
    metadata:
      labels:
        app: hello-server
    spec:
      containers:
      - name: hello-server
        image: registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images/hello-server
        ports:
        - containerPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      labels:
        app: nginx-demo
    spec:
      containers:
      - image: nginx
        name: nginx
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  selector:
    app: nginx-demo
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-server
  name: hello-server
spec:
  selector:
    app: hello-server
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 9000

ingress配置

  1. 域名访问
    apiVersion: networking.k8s.io/v1
    kind: Ingress  
    metadata:
      name: ingress-host-bar
    spec:
      ingressClassName: nginx
      rules:
      - host: "hello.atguigu.com"
        http:
          paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: hello-server
                port:
                  number: 8000
      - host: "demo.atguigu.com"
        http:
          paths:
          - pathType: Prefix
            path: "/nginx"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
            backend:
              service:
                name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
                port:
                  number: 8000
    
  2. 路径重写
    apiVersion: networking.k8s.io/v1
    kind: Ingress  
    metadata:
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
      name: ingress-host-bar
    spec:
      ingressClassName: nginx
      rules:
      - host: "hello.atguigu.com"
        http:
          paths:
          - pathType: Prefix
            path: "/"
            backend:
              service:
                name: hello-server
                port:
                  number: 8000
      - host: "demo.atguigu.com"
        http:
          paths:
          - pathType: Prefix
            path: "/nginx(/|$)(.*)"  # 把请求会转给下面的服务,下面的服务一定要能处理这个路径,不能处理就是404
            backend:
              service:
                name: nginx-demo  ## java,比如使用路径重写,去掉前缀nginx
                port:
                  number: 8000
    
  3. 流量限制
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-limit-rate
      annotations:
        nginx.ingress.kubernetes.io/limit-rps: "1"
    spec:
      ingressClassName: nginx
      rules:
      - host: "haha.atguigu.com"
        http:
          paths:
          - pathType: Exact
            path: "/"
            backend:
              service:
                name: nginx-demo
                port:
                  number: 8000
    

存储抽象

环境准备

以NFS作为底层存储服务。

  1. 所有节点安装
    #所有机器安装
    yum install -y nfs-utils
    
  2. 主节点配置
    #nfs主节点
    echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
    
    mkdir -p /nfs/data
    systemctl enable rpcbind --now
    systemctl enable nfs-server --now
    #配置生效
    exportfs -r
    
  3. 从节点执行挂载
    # 查看可挂载目录
    showmount -e 172.31.0.4
    
    #执行以下命令挂载 nfs 服务器上的共享目录到本机路径 /root/nfsmount
    mkdir -p /nfs/data
    
    mount -t nfs 172.31.0.4:/nfs/data /nfs/data
    # 写入一个测试文件
    echo "hello nfs server" > /nfs/data/test.txt
    

存储挂载

  1. 原生挂载方式

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: nginx-pv-demo
      name: nginx-pv-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx-pv-demo
      template:
        metadata:
          labels:
            app: nginx-pv-demo
        spec:
          containers:
          - image: nginx
            name: nginx
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          volumes:
            - name: html
              nfs:
                server: 172.31.0.4
                path: /nfs/data/nginx-pv
    
  2. PV&PVC

    PV:持久卷(Persistent Volume),将应用需要持久化的数据保存到指定位置
    PVC:持久卷申明(Persistent Volume Claim),申明需要使用的持久卷规格

    创建静态PV池

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv01-10m
    spec:
      capacity:
        storage: 10M
      accessModes:
        - ReadWriteMany
      storageClassName: nfs
      nfs:
        path: /nfs/data/01
        server: 172.31.0.4
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv02-1gi
    spec:
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteMany
      storageClassName: nfs
      nfs:
        path: /nfs/data/02
        server: 172.31.0.4
    ---
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv03-3gi
    spec:
      capacity:
        storage: 3Gi
      accessModes:
        - ReadWriteMany
      storageClassName: nfs
      nfs:
        path: /nfs/data/03
        server: 172.31.0.4
    
    kubectl apply -f xxx-pv.yaml
    

    创建PVC

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: nginx-pvc
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 200Mi
      storageClassName: nfs
    

    绑定PVC

    kubectl apply -f xxx-pvc.yaml
    

    创建Pod绑定PVC

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: nginx-deploy-pvc
      name: nginx-deploy-pvc
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx-deploy-pvc
      template:
        metadata:
          labels:
            app: nginx-deploy-pvc
        spec:
          containers:
          - image: nginx
            name: nginx
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          volumes:
            - name: html
              persistentVolumeClaim:
                claimName: nginx-pvc
    
  3. ConfigMap

    抽取应用配置,并且可以自动更新
    以Redis为例子

    # 创建配置,redis保存到k8s的etcd;
    kubectl create cm redis-conf --from-file=redis.conf
    
    # 该yaml文件可以以命令行的方式获取
    # kubectl get cm redis-conf --oyaml
    apiVersion: v1
    data:    #data是所有真正的数据,key:默认是文件名   value:配置文件的内容
      redis.conf: |
        appendonly yes
    kind: ConfigMap
    metadata:
      name: redis-conf
      namespace: default
    

    创建Pod

    apiVersion: v1
    kind: Pod
    metadata:
      name: redis
    spec:
      containers:
      - name: redis
        image: redis
        command:
          - redis-server
          - "/redis-master/redis.conf"  #指的是redis容器内部的位置
        ports:
        - containerPort: 6379
        volumeMounts:
        - mountPath: /data
          name: data
        - mountPath: /redis-master
          name: config
      volumes:
        - name: data
          emptyDir: {}
        - name: config
          configMap:
            name: redis-conf
            items:
            - key: redis.conf
              path: redis.conf
    

    检查默认配置

    kubectl exec -it redis -- redis-cli
    
    127.0.0.1:6379> CONFIG GET appendonly
    127.0.0.1:6379> CONFIG GET requirepass
    

    修改ConfigMap

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: example-redis-config
    data:
      redis-config: |
        maxmemory 2mb
        maxmemory-policy allkeys-lru 
    

    检查更新

    kubectl exec -it redis -- redis-cli
    
    127.0.0.1:6379> CONFIG GET maxmemory
    127.0.0.1:6379> CONFIG GET maxmemory-policy
    
  4. Secret

    Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 将这些信息放在 secret 中比放在 Pod的定义或者 容器镜像 中来说更加安全和灵活。

    kubectl create secret docker-registry leifengyang-docker \
    --docker-username=leifengyang \
    --docker-password=Lfy123456 \
    --docker-email=534096094@qq.com
    
    ##命令格式
    kubectl create secret docker-registry regcred \
      --docker-server=<你的镜像仓库服务器> \
      --docker-username=<你的用户名> \
      --docker-password=<你的密码> \
      --docker-email=<你的邮箱地址>
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: private-nginx
    spec:
      containers:
      - name: private-nginx
        image: leifengyang/guignginx:v1.0
      imagePullSecrets:
      - name: leifengyang-docker
    

你可能感兴趣的:(云原生,云原生,docker,kubernetes)