提交 4d9a6b90 编写于 作者: 阳明的博客's avatar 阳明的博客

add pages content

上级 1160e587
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDeps
# 从Docker到Kubernetes进阶
从 Docker 入门一步步迁移到 Kubernetes 的进阶课程
在线浏览:[https://www.qikqiak.com/k8s-book](https://www.qikqiak.com/k8s-book/)
GitHub地址:[https://github.com/cnych/kubernetes-learning/](https://github.com/cnych/kubernetes-learning/)
视频课程在线地址:[https://youdianzhishi.com/course/6n8xd6/](https://youdianzhishi.com/course/6n8xd6/)
## 介绍
[Kubernetes](http://kubernetes.io/)是Google基于Borg开源的容器编排调度引擎,作为[CNCF](http://cncf.io/)(Cloud Native Computing Foundation)最重要的组件之一,它的目标不仅仅是一个编排系统,而是提供一个规范,可以让你来描述集群的架构,定义服务的最终状态,`Kubernetes` 可以帮你将系统自动地达到和维持在这个状态。`Kubernetes` 作为云原生应用的基石,相当于一个云操作系统,其重要性不言而喻。
![从Docker到Kubernetes进阶](http://sdn.haimaxy.com/covers/2018/4/21/c4082e0f09c746aa848279a2567cffed.png)
之前一直有同学跟我说我 `Docker` 掌握得还可以,但是不知道怎么使用 `Kubernetes`,网上的其他关于 `Kubernetes` 的课程费用又太高,本书就是为你们准备的,当然如果你不了解 `Docker`,不了解 `Kubernetes`,都没有关系,我们会从 `Docker` 入门一步步深入,到 `Kubernetes` 的进阶使用的。所以大家完全没必要担心。
学完本课程以后,你将会对 `Docker``Kubernetes` 有一个更加深入的认识,我们会讲到:
* `Docker` 的一些常用方法,当然我们的重点会在 Kubernetes 上面
* 会用 `kubeadm` 来搭建一套 `Kubernetes` 的集群
* 理解 `Kubernetes` 集群的运行原理
* 常用的一些控制器使用方法
* 还有 `Kubernetes` 的一些调度策略
* `Kubernetes`的运维
* 包管理工具 `Helm` 的使用
* 最后我们会实现基于 Kubernetes 的 CI/CD
## 社区&读者交流
* 博客:[阳明的博客](https://qikqiak.com/)
* 微信群:`k8s`技术圈,扫描我的微信二维码,[阳明](https://qikqiak.com/page/about/),或直接搜索微信号**iEverything**后拉您入群,请增加备注(k8s或kubernetes)
* 知乎专栏:[k8s技术圈](https://zhuanlan.zhihu.com/kube100)
* 开发者头条:[k8s技术圈](https://toutiao.io/subjects/268333)
* 微信公众号:扫描下面的二维码关注微信公众号`k8s技术圈`
![k8s公众帐号](./docs/images/k8s-qrcode.png)
* 优点知识:[优点知识](https://youdianzhishi.com/)是一个综合的技术学习平台,本书配套的视频教程将会发布在该平台上面,感兴趣的朋友可以扫描下发的二维码关注自己感兴趣的课程。
![优点知识服务号](./docs/images/ydzs-qrcode.png)
![优点知识小程序](./docs/images/ydzs-xcx.png)
# 目录
### 介绍
* [序言](README.md)
* [课程介绍](docs/1.课程介绍.md)
### Docker 基础
* [Docker 简介](docs/2.Docker 简介.md)
* [镜像和容器的基本操作](docs/3.镜像和容器的基本操作.md)
* [Dockerfile 定制镜像](docs/4.Dockerfile 定制镜像.md)
* [私有镜像仓库](docs/5.私有镜像仓库.md)
* [数据共享与持久化](docs/6.数据共享与持久化.md)
* [Docker 的网络模式](docs/7.Docker的网络模式.md)
### Docker 三架马车
* [Docker Compose](docs/8.Docker Compose.md)
* [Docker Machine](docs/9.Docker Machine.md)
* [Docker Swarm](docs/10.Docker Swarm.md)
### Docker 实践
* [图形化管理和监控](docs/11.图形化管理和监控.md)
* [Docker 的多阶段构建](docs/12.Docker的多阶段构建.md)
* [Dockerfile 最佳实践](docs/13.Dockerfile最佳实践.md)
### Kubernetes 基础
* [Kubernetes 初体验](docs/14.Kubernetes初体验.md)
* [基本概念与组件](docs/15.基本概念与组件.md)
### kubeadm 搭建集群
* [使用 kubeadm 搭建集群环境](docs/16.用 kubeadm 搭建集群环境.md)
* [安装 Dashboard 插件](docs/17.安装 Dashboard 插件.md)
### 深入理解 Pod
* [YAML 文件](docs/18.YAML 文件.md)
* [静态 Pod](docs/19.静态 Pod.md)
* [Pod Hook](docs/20.Pod Hook.md)
* [Pod 的健康检查](docs/21.健康检查.md)
* [初始化容器](docs/22.初始化容器.md)
### 常用对象操作:
* [Replication Controller 与 Replica Set](docs/23.使用RC管理Pod.md)
* [Deployment](docs/24.Deployment 使用.md)
* [HPA](docs/25.Pod 水平自动伸缩.md)
* [Job/CronJob](docs/26.Job与Cronjob 的使用.md)
* [Service](docs/27.Service.md)
* [ConfigMap](docs/28.ConfigMap.md)
* [Secret](docs/29.Secret.md)
* [RBAC](docs/30.RBAC.md)
* [部署Wordpress示例](docs/31.部署 Wordpress 示例.md)
* [DaemonSet 和 StatefulSet](docs/32.DaemonSet 与 StatefulSet.md)
### 持久化存储:
* [PV](docs/33.PV.md)
* [PVC](docs/34.PVC.md)
* [StorageClass](docs/35.StorageClass.md)
### 服务发现
* [kubedns](docs/39.kubedns.md)
* [ingress 安装配置](docs/40.ingress.md)
* [ingress tls 和 path 的使用](docs/41.ingress config.md)
### 包管理工具 Helm
* [Helm 的安装使用](docs/42.Helm安装.md)
* [Helm 的基本使用](docs/43.Helm基本使用.md)
* [Helm 模板之内置函数和Values](docs/44.Helm模板之内置函数和Values.md)
* [Helm 模板之模板函数与管道](docs/45.Helm模板之模板函数与管道.md)
* [Helm 模板之控制流程](docs/46.Helm模板之控制流程.md)
* [Helm 模板之命名模板](docs/47.Helm模板之命名模板.md)
* [Helm 模板之其他注意事项](docs/48.Helm模板之其他注意事项.md)
* [Helm Hooks](docs/49.Helm Hooks.md)
### 调度器
* [Kubernetes 调度器介绍](docs/50.Kubernetes调度策略.md)
* [Kubernetes 亲和性调度](docs/51.Kubernetes亲和性调度.md)
### 集群监控
* [手动安装 Prometheus](docs/52.Prometheus基本使用.md)
* [监控 Kubernetes 集群应用](docs/53.监控Kubernetes集群应用.md)
* [监控 Kubernetes 集群节点](docs/54.监控Kubernetes集群节点.md)
* [监控 Kubernetes 常用资源对象](docs/55.监控Kubernetes常用资源对象.md)
* [Grafana 的安装使用](docs/56.Grafana的安装使用.md)
* [AlertManager 的使用](docs/57.AlertManager的使用.md)
* [Prometheus Operator 的安装](docs/58.Prometheus Operator.md)
* [自定义Prometheus Operator 监控项](docs/59.自定义Prometheus Operator 监控项.md)
* [Prometheus Operator高级配置](docs/60.Prometheus Operator高级配置.md)
### 日志收集
* [日志收集架构](docs/61.日志收集架构.md)
* [搭建 EFK 日志系统](docs/62.搭建 EFK 日志系统.md)
### CI/CD:
* [动态 Jenkins Slave](docs/36.Jenkins Slave.md)
* [Jenkins Pipeline 部署 Kubernetes 应用](docs/37.Jenkins Pipeline.md)
* [Jenkins BlueOcean](docs/38.Jenkins BlueOcean.md)
* [Harbor](docs/63.Harbor.md)
* [Gitlab](docs/64.Gitlab.md)
* [Gitlab CI](docs/65.Gitlab CI.md)
* [Devops](docs/66.devops.md)
### 其他:
* [集群升级](docs/67.Upgrade集群.md)
{
"title": "从 Docker 到 Kubernetes 进阶手册",
"description": "从 Docker 入门一步步迁移到 Kubernetes 的进阶课程学习指南",
"language": "zh-hans",
"author": "阳明",
"links": {
"sidebar": {
"阳明的博客": "https://www.qikqiak.com",
"优点知识": "https://youdianzhishi.com",
"我们一起学istio技术": "https://www.qikqiak.com/istio-book/",
"python微服务实战": "https://www.qikqiak.com/tdd-book/"
}
},
"plugins": [
"prism", "prism-themes", "-highlight",
"github",
"codesnippet",
"splitter",
"simple-page-toc",
"page-toc-button",
"image-captions",
"back-to-top-button",
"-lunr", "-search", "search-plus",
"github-buttons@2.1.0",
"favicon@^0.0.2",
"tbfed-pagefooter@^0.0.1",
"theme-default",
"sitemap-general",
"3-ba",
"ga",
"adsense"
],
"pluginsConfig": {
"theme-default": {
"showLevel": true
},
"prism": {
"css": [
"prism-themes/themes/prism-hopscotch.css"
]
},
"github": {
"url": "https://github.com/cnych/kubernetes-learning"
},
"simple-page-toc": {
"maxDepth": 3,
"skipFirstH1": true
},
"image-captions": {
"caption": "_CAPTION_"
},
"github-buttons": {
"repo": "cnych/kubernetes-learning",
"types": ["star"],
"size": "small"
},
"sitemap-general": {
"prefix": "https://www.qikqiak.com/k8s-book/"
},
"tbfed-pagefooter": {
"copyright": "Copyright © qikqiak.com 2018",
"modify_label": "Updated: ",
"modify_format": "YYYY-MM-DD HH:mm:ss"
},
"favicon": {
"shortcut": "favicon.ico",
"bookmark": "favicon.ico"
},
"3-ba": {
"token": "d611849735f187dd788dc054908f7d7a"
},
"ga": {
"token": "UA-69668147-3"
},
"adsense": {
"client": "ca-pub-5376999672787220",
"slot": "3100272140",
"format": "auto",
"element": ".page-inner section",
"position": "bottom"
}
}
}
apiVersion: v1
kind: ConfigMap
metadata:
name: cm-demo1
data:
data.1: hello
data.2: world
config: |
property.1=value-1
property.2=value-2
property.3=value-3
\ No newline at end of file
apiVersion: v1
kind: Pod
metadata:
name: testcm1-pod
spec:
containers:
- name: testcm1
image: busybox
command: ["/bin/sh", "-c", "env"]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo4
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo4
key: db.port
envFrom:
- configMapRef:
name: cm-demo2
\ No newline at end of file
apiVersion: v1
kind: Pod
metadata:
name: testcm2-pod
spec:
containers:
- name: testcm2
image: busybox
command: ["/bin/sh", "-c", "echo $(DB_HOST) $(DB_PORT)"]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo4
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo4
key: db.port
apiVersion: v1
kind: Pod
metadata:
name: testcm4-pod
spec:
containers:
- name: testcm4
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/redis.conf"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo3
\ No newline at end of file
apiVersion: v1
kind: Pod
metadata:
name: testcm5-pod
spec:
containers:
- name: testcm5
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/path/to/mysql.conf"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo2
items:
- key: mysql.conf
path: path/to/mysql.conf
\ No newline at end of file
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx-ds
labels:
app: nginx
spec:
template:
metadata:
labels:
k8s-app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- name: htpp
containerPort: 80
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: admin
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
\ No newline at end of file
# 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.
# ------------------- Dashboard Secret ------------------- #
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kube-system
type: Opaque
---
# ------------------- Dashboard Service Account ------------------- #
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
---
# ------------------- Dashboard Role & Role Binding ------------------- #
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
rules:
# Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
# Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create"]
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
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 from heapster.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system
---
# ------------------- Dashboard Deployment ------------------- #
kind: Deployment
apiVersion: apps/v1beta2
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
# 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
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
# ------------------- Dashboard Service ------------------- #
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
ports:
- port: 443
targetPort: 8443
type: NodePort
selector:
k8s-app: kubernetes-dashboard
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1wc3BtZyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjczM2M4OTU1LWI4YmYtMTFlOC1iMzc4LTAyNTAwMDAwMDAwMSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.J1Ii8-bSEe86_ORS97Xqe7yNz3ET2x7mfV9VW4bojbOM212Dv8jnpDbP7ZAQYaTXnr5_QkVAWv5Qqqng4OzeR3ykW1u51x6oyH2F_wFGPB2xwgow-2UTLy5dsRrPkiMv3lcPJ34BaVbjojzfLUI0Vvl8DPID_tvuZzlX1AVCgoQutOFAMQgmCnlezspisYjTJVgFD2vd7hVe5jN16r1oNRn9EYK3xAHyum3L9HcMg3cnOPFf8WlhVyAkMeFGG8qNjWtzW6gmXkyaM3NATh7-YdM9hKqkgm2DmvCkkB_NNtchhU_EdwD0xt4VcNQZQHFaYWYxmpmeJPBFPewdL-76mw
\ No newline at end of file
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhZG1pbi10b2tlbi1nbXdzcCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImY4ZDI3NjYyLTVhYjEtMTFlOC1hMTAxLTUyNTQwMGRiNGRmNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphZG1pbiJ9.bkLMp5QmJ4-VRxQrteA8JEkPtN6H7GZUAuWdxSxWeORpnd3oPSDX7iElH43tWZyaduTO0HHAC1X9fTI7gAVbKZHAlivbyF07wU5a0DwVG-Xw-M_PcnL42UI9FbCC4D8xCWvwWbRS_fPHTy7kkOCa-fZT26VsiT2tG-xTqIp1xaG6i87hK0dmFTB7NPdhRFY7L7Ceu0EBzpVd4zkglyFfJkoGjAQ7ShigYIzHIrf41U07OHtA34w7-8GmilNreGugP-wX1rWvki5afwL8iRDYFBzXKoZNZk25HOrp7--9WsjRRx14zvm0-8rDiXuFzl0yZaM3-dfslb08ysM1SAwMOA
\ No newline at end of file
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
namespace: test
labels:
app: nginx-demo
spec:
replicas: 3
revisionHistoryLimit: 15
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: nginxweb
apiVersion: v1
kind: Service
metadata:
name: ngxdemo
spec:
selector:
app: app
type: NodePort
ports:
- name: http
protocol: TCP
port: 80
targetPort: nginxweb
dingtalkserv @ 36065de3
Subproject commit 36065de354bb589f08d1e1a5631804ce1d08b54f
apiVersion: v1
kind: Pod
metadata:
name: test-api
spec:
containers:
- name: test-api
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh", "-c", "env"]
dnsPolicy: ClusterFirst
node01
kube-dns CM
cluster.local kubedns
www.haimaxy.com -> node01
kube-dns CM
kube-dns ->.cluster.local ->kubedns
-> acme.local -> 1.2.3.4
-> www.haimaxy.com -> [8.8.8.8, 8.8.4.4]
nginx-service.default.svc.cluster.local
nginx-service.default
nginx-service
redis-0.redis-service.kube-ops.svc.cluster.local
redis-1.redis-service.kube-ops.svc.cluster.local
clusterIP
\ No newline at end of file
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
names: nginx-service
spec:
selector:
app: nginx
ports:
- port: 5000
targetPort: 80
\ No newline at end of file
docker-multi-stage-demo @ 571b0300
Subproject commit 571b03002ff43592ca62dfbda570fc30479ab6b8
此差异已折叠。
# 1. 课程介绍
之前一直有同学跟我说我`Docker`掌握得还可以,但是不知道怎么使用`Kubernetes`,网上的其他关于 Kubernetes 的课程费用又太高,这节课就是为你们准备的,当然如果你不了解 Docker,不了解 Kubernetes,都没有关系,我们这个课程会从 Docker 入门一步步深入,到 Kubernetes 的进阶使用的。所以大家完全没必要担心。
​​![course logo](./images/course-logo.png)
学完本课程以后,你将会对 Docker 和 Kubernetes 有一个更加深入的认识,我们会讲到:
* Docker 的一些常用方法,当然我们的重点会在 Kubernetes 上面
* 会用 kubeadm 来搭建一套 Kubernetes 的集群
* 理解 Kubernetes 集群的运行原理
* 常用的一些控制器使用方法
* 还有 Kubernetes 的一些调度策略
* Kubernetes的运维
* 包管理工具 Helm 的使用
* 最后我们会实现基于 Kubernetes 的 CI/CD
---
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![qrcode](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
# 10. Docker Swarm
## 基本概念
`Swarm`是使用[SwarmKit](https://github.com/docker/swarmkit/)构建的 Docker 引擎内置(原生)的集群管理和编排工具。`Docker Swarm`是 Docker 官方三剑客项目之一,提供 Docker 容器集群服务,是 Docker 官方对容器云生态进行支持的核心方案。
使用它,用户可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。Swarm mode 内置 kv 存储功能,提供了众多的新特性,比如:具有容错能力的去中心化设计、内置服务发现、负载均衡、路由网格、动态伸缩、滚动更新、安全传输等。使得 Docker 原生的 Swarm 集群具备与`Mesos``Kubernetes`竞争的实力。使用 Swarm 集群之前需要了解以下几个概念。
### 节点
运行 Docker 的主机可以主动初始化一个 Swarm 集群或者加入一个已存在的 Swarm 集群,这样这个运行 Docker 的主机就成为一个 Swarm 集群的节点 (node) 。节点分为`管理 (manager) 节点和工作 (worker) 节点`
管理节点用于`Swarm`集群的管理,`docker swarm`命令基本只能在管理节点执行(节点退出集群命令`docker swarm leave`可以在工作节点执行)。一个 Swarm 集群可以有多个管理节点,但只有一个管理节点可以成为`leader`,leader 通过`raft`协议实现。
工作节点是任务执行节点,管理节点将服务 (`service`) 下发至工作节点执行。管理节点默认也作为工作节点。你也可以通过配置让服务只运行在管理节点。来自`Docker`官网的这张图片形象的展示了集群中管理节点与工作节点的关系。
![docker swarm structrue](./images/docker-swarm-structrue.png)
​​
### 服务和任务
`任务(Task)`是 Swarm 中的最小的调度单位,目前来说就是一个单一的容器;`服务(Services)`是指一组任务的集合,服务定义了任务的属性。服务有两种模式:
* `replicated services`按照一定规则在各个工作节点上运行指定个数的任务。
* `global services`每个工作节点上运行一个任务
两种模式通过`docker service create``--mode`参数指定。来自 Docker 官网的这张图片形象的展示了容器、任务、服务的关系。
![docker swarm task service](./images/docker-swarm-task-service.png)
​​
## 初始化集群
我们这里利用上一节的`docker machine`来充当集群的主机,首先先创建一个`manager`节点,然后在该节点上执行初始化集群命令:
```shell
☁ ~ docker-machine create -d virtualbox manager
Running pre-create checks...
Creating machine...
(manager) Copying /Users/ych/.docker/machine/cache/boot2docker.iso to /Users/ych/.docker/machine/machines/manager/boot2docker.iso...
(manager) Creating VirtualBox VM...
(manager) Creating SSH key...
(manager) Starting the VM...
(manager) Check network to re-create if needed...
(manager) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env manager
☁ ~ docker-machine env manager
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.101:2376"
export DOCKER_CERT_PATH="/Users/ych/.docker/machine/machines/manager"
export DOCKER_MACHINE_NAME="manager"
# Run this command to configure your shell:
# eval $(docker-machine env manager)
☁ ~ eval $(docker-machine env manager)
☁ ~ docker-machine ssh manager
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\_______/
_ _ ____ _ _
| |__ ___ ___ | |_|___ \ __| | ___ ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__| < __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 18.03.1-ce, build HEAD : cb77972 - Thu Apr 26 16:40:36 UTC 2018
Docker version 18.03.1-ce, build 9ee9f40
docker@manager:~$ docker swarm init --advertise-addr 192.168.99.101
Swarm initialized: current node (3gsjpckj5ag1vvdg44fgzylow) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-1aqikkhsz91l4n7k9ig3xinjz0iv0fh4gcrlhp9mk3643rblca-aqgqldlrw33k8heiao7yx27w5 192.168.99.101:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
```
执行`docker swarm init`命令的节点自动成为管理节点。
## 增加工作节点
管理节点初始化完成后,然后同样的用`docker-machine`创建工作节点,然后将其加入到管理节点之中去即可:
```shell
☁ ~ docker-machine create -d virtualbox worker1
Running pre-create checks...
Creating machine...
(worker1) Copying /Users/ych/.docker/machine/cache/boot2docker.iso to /Users/ych/.docker/machine/machines/worker1/boot2docker.iso...
(worker1) Creating VirtualBox VM...
(worker1) Creating SSH key...
(worker1) Starting the VM...
(worker1) Check network to re-create if needed...
(worker1) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env worker1
☁ ~ docker-machine ssh worker1
## .
## ## ## ==
## ## ## ## ## ===
/"""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\_______/
_ _ ____ _ _
| |__ ___ ___ | |_|___ \ __| | ___ ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__| < __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 18.03.1-ce, build HEAD : cb77972 - Thu Apr 26 16:40:36 UTC 2018
Docker version 18.03.1-ce, build 9ee9f40
docker@worker1:~$ docker swarm join --token SWMTKN-1-1aqikkhsz91l4n7k9ig3xinjz0iv0fh4gcrlhp9mk364
3rblca-aqgqldlrw33k8heiao7yx27w5 192.168.99.101:2377
This node joined a swarm as a worker.
```
我们可以看到上面的提示信息:**This node joined a swarm as a worker.**,表明节点已经加入到`swarm`集群之中了。
## 查看集群
经过上边的两步,我们已经拥有了一个最小的 Swarm 集群,包含一个管理节点和两个工作节点。
管理节点使用`docker node ls`查看集群:
```shell
☁ ~ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
3gsjpckj5ag1vvdg44fgzylow * manager Ready Active Leader 18.03.1-ce
cxmj5lr0vbwo1em9y9oang5m8 worker1 Ready Active 18.03.1-ce
ksruum3uc1c265ywm4kn9a88g worker2 Ready Active 18.03.1-ce
☁ ~ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
☁ ~ docker service create --replicas 3 -p 80:80 --name nginx nginx:1.13.7-alpine
4k9cbna8ive87p4or9mny9kfs
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service converged
☁ ~ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
manager * virtualbox Running tcp://192.168.99.101:2376 v18.03.1-ce
worker1 - virtualbox Running tcp://192.168.99.102:2376 v18.03.1-ce
worker2 - virtualbox Running tcp://192.168.99.103:2376 v18.03.1-ce
☁ ~ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
4k9cbna8ive8 nginx replicated 3/3 nginx:1.13.7-alpine *:80->80/tcp
☁ ~ docker service ps nginx
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
r7hmzkqsri8p nginx.1 nginx:1.13.7-alpine worker1 Running Running about a minute ago
y0xgrfwmjfrj nginx.2 nginx:1.13.7-alpine worker2 Running Running about a minute ago
j8k7be8xkbg3 nginx.3 nginx:1.13.7-alpine manager Running Running about a minute ago
```
使用`docker service logs`来查看某个服务的日志。
```shell
☁ ~ docker service logs nginx
```
使用`docker service rm`来从 Swarm 集群移除某个服务:
```shell
☁ ~ docker service rm nginx
nginx
```
正如之前使用`docker-compose.yml`来一次配置、启动多个容器,在`Swarm`集群中也可以使用`compose`文件(docker-compose.yml)来配置、启动多个服务。
上一节中,我们使用`docker service create`一次只能部署一个服务,使用`docker-compose.yml`我们可以一次启动多个关联的服务。
我们以在`Swarm`集群中部署`WordPress`为例进行说明:(docker-compose.yml)
```yaml
version: "3"
services:
wordpress:
image: wordpress
ports:
- 80:80
networks:
- overlay
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
deploy:
mode: replicated
replicas: 3
db:
image: mysql
networks:
- overlay
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
deploy:
placement:
constraints: [node.role == manager]
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
volumes:
db-data:
networks:
overlay:
```
其中**constraints: [node.role == manager]**是调度策略,文档地址:https://docs.docker.com/swarm/scheduler/filter/
在 Swarm 集群管理节点新建该文件,其中的 visualizer 服务提供一个可视化页面,我们可以从浏览器中很直观的查看集群中各个服务的运行节点。
在 Swarm 集群中使用 docker-compose.yml 我们用`docker stack`命令,下面我们对该命令进行详细讲解。
### 部署服务
部署服务使用`docker stack deploy`,其中`-c`参数指定 compose 文件名。
```shell
$ docker stack deploy -c docker-compose.yml wordpress
```
### 查看服务
```shell
$ docker stack ls
NAME SERVICES
wordpress 3
```
### 移除服务
要移除服务,使用`docker stack down`:
```shell
$ docker stack down wordpress
Removing service wordpress_db
Removing service wordpress_visualizer
Removing service wordpress_wordpress
Removing network wordpress_overlay
Removing network wordpress_default
```
该命令不会移除服务所使用的`数据卷`,如果你想移除数据卷请使用`docker volume rm`
---
[点击查看本文视频](https://youdianzhishi.com/course/6n8xd6/)
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![k8s技术圈二维码](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
# 11. 图形化管理和监控
下面我们介绍几个可以用图形化的方式来管理`Docker`的工具。
> Shipyard:https://github.com/shipyard/shipyard(已停止维护)
## Portainer
[Portainer](https://portainer.io/)(基于 Go)是一个轻量级的管理界面,可让您轻松管理`Docker`主机或`Swarm`集群。
`Portainer`的使用意图是简单部署。它包含可以在任何 Docker 引擎上运行的单个容器(Docker for Linux 和 Docker for Windows)。
`Portainer`允许您管理 Docker 容器、image、volume、network 等。 它与独立的 Docker 引擎和 Docker Swarm 兼容。
Docker 命令安装:
```shell
$ docker volume create portainer_data
$ docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer
```
Swarm集群部署:
```shell
$ docker volume create portainer_data
$ docker service create \
--name portainer \
--publish 9000:9000 \
--replicas=1 \
--constraint 'node.role == manager' \
--mount type=bind,src=//var/run/docker.sock,dst=/var/run/docker.sock \
--mount type=volume,src=portainer_data,dst=/data \
portainer/portainer \
-H unix:///var/run/docker.sock
```
Docker Compose 部署:
```yaml
version: '2'
services:
portainer:
image: portainer/portainer
command: -H unix:///var/run/docker.sock
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
volumes:
portainer_data:
```
![portainer](./images/docker-ui-portainer.png)
## Rancher
`Rancher`是一个开源的企业级容器管理平台。通过`Rancher`,企业不必自己使用一系列的开源软件去从头搭建容器服务平台。`Rancher`提供了在生产环境中使用管理`Docker``Kubernetes`的全栈化容器部署与管理平台。
​​![rancher](./images/docker-ui-rancher.png)
在后面学习`kubernetes`的课程的时候会给大家演示,用于我们快速搭建一个可运行`kubernetes`集群环境,非常方便。
## cAdvisor
`cAdvisor``Google`开发的容器监控工具,我们来看看 cAdvisor 有什么能耐。
* 监控 Docker Host
cAdvisor 会显示当前 host 的资源使用情况,包括 CPU、内存、网络、文件系统等。
* 监控容器
点击 Docker Containers 链接,显示容器列表。点击某个容器,比如 sysdig,进入该容器的监控页面。
以上就是 cAdvisor 的主要功能,总结起来主要两点:
* 展示 Host 和容器两个层次的监控数据。
* 展示历史变化数据。
由于`cAdvisor`提供的操作界面略显简陋,而且需要在不同页面之间跳转,并且只能监控一个 host,这不免会让人质疑它的实用性。但 cAdvisor 的一个亮点是它可以将监控到的数据导出给第三方工具,由这些工具进一步加工处理。
我们可以把 cAdvisor 定位为一个监控数据收集器,收集和导出数据是它的强项,而非展示数据。
cAdvisor 支持很多第三方工具,其中就包括后面我们重点要学习的`Prometheus`
```shell
$ docker run \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker/:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
--publish=8080:8080 \
--detach=true \
--name=cadvisor \
google/cadvisor:latest
```
通过访问地址:http://127.0.0.1:8080/containers/ 可以查看所有容器信息:
![docker cAdvisor](./images/docker-cadvisor.png)
​​
除此之外,cAdvisor 还提供了一个 Rest API:https://github.com/google/cadvisor/blob/master/docs/api.md
cAdvisor 通过该 REST API 暴露监控数据,格式如下:
```
http://<hostname>:<port>/api/<version>/<request>
```
---
[点击查看本文视频](https://youdianzhishi.com/course/6n8xd6/)
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![k8s技术圈二维码](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
# 12. Docker 的多阶段构建
`Docker`的口号是 **Build,Ship,and Run Any App,Anywhere**,在我们使用 Docker 的大部分时候,的确能感觉到其优越性,但是往往在我们 Build 一个应用的时候,是将我们的源代码也构建进去的,这对于类似于 golang 这样的编译型语言肯定是不行的,因为实际运行的时候我只需要把最终构建的二进制包给你就行,把源码也一起打包在镜像中,需要承担很多风险,即使是脚本语言,在构建的时候也可能需要使用到一些上线的工具,这样无疑也增大了我们的镜像体积。
## 示例
比如我们现在有一个最简单的 golang 服务,需要构建一个最小的`Docker` 镜像,源码如下:
```go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
router := gin.Default()
router.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "PONG")
})
router.Run(":8080")
}
```
## 解决方案
我们最终的目的都是将最终的可执行文件放到一个最小的镜像(比如`alpine`)中去执行,怎样得到最终的编译好的文件呢?基于 `Docker` 的指导思想,我们需要在一个标准的容器中编译,比如在一个 Ubuntu 镜像中先安装编译的环境,然后编译,最后也在该容器中执行即可。
但是如果我们想把编译后的文件放置到 `alpine` 镜像中执行呢?我们就得通过上面的 Ubuntu 镜像将编译完成的文件通过 `volume` 挂载到我们的主机上,然后我们再将这个文件挂载到 `alpine` 镜像中去。
这种解决方案理论上肯定是可行的,但是这样的话在构建镜像的时候我们就得定义两步了,第一步是先用一个通用的镜像编译镜像,第二步是将编译后的文件复制到 `alpine` 镜像中执行,而且通用镜像编译后的文件在 `alpine` 镜像中不一定能执行。
定义编译阶段的 `Dockerfile`:(保存为**Dockerfile.build**)
```docker
FROM golang
WORKDIR /go/src/app
ADD . /go/src/app
RUN go get -u -v github.com/kardianos/govendor
RUN govendor sync
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server
```
定义`alpine`镜像:(保存为**Dockerfile.old**)
```docker
FROM alpine:latest
RUN apk add -U tzdata
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
WORKDIR /root/
COPY app-server .
CMD ["./app-server"]
```
根据我们的执行步骤,我们还可以简单定义成一个脚本:(保存为**build.sh**)
```shell
#!/bin/sh
echo Building cnych/docker-multi-stage-demo:build
docker build -t cnych/docker-multi-stage-demo:build . -f Dockerfile.build
docker create --name extract cnych/docker-multi-stage-demo:build
docker cp extract:/go/src/app/app-server ./app-server
docker rm -f extract
echo Building cnych/docker-multi-stage-demo:old
docker build --no-cache -t cnych/docker-multi-stage-demo:old . -f Dockerfile.old
rm ./app-server
```
当我们执行完上面的构建脚本后,就实现了我们的目标。
## 多阶段构建
有没有一种更加简单的方式来实现上面的镜像构建过程呢?**Docker 17.05**版本以后,官方就提供了一个新的特性:`Multi-stage builds`(多阶段构建)。
使用多阶段构建,你可以在一个 `Dockerfile` 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并表示开始一个新的构建阶段。你可以很方便的将一个阶段的文件复制到另外一个阶段,在最终的镜像中保留下你需要的内容即可。
我们可以调整前面一节的 `Dockerfile` 来使用多阶段构建:(保存为**Dockerfile**)
```docker
FROM golang AS build-env
ADD . /go/src/app
WORKDIR /go/src/app
RUN go get -u -v github.com/kardianos/govendor
RUN govendor sync
RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server
FROM alpine
RUN apk add -U tzdata
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY --from=build-env /go/src/app/app-server /usr/local/bin/app-server
EXPOSE 8080
CMD [ "app-server" ]
```
现在我们只需要一个`Dockerfile`文件即可,也不需要拆分构建脚本了,只需要执行 build 命令即可:
```shell
$ docker build -t cnych/docker-multi-stage-demo:latest .
```
默认情况下,构建阶段是没有命令的,我们可以通过它们的索引来引用它们,第一个 FROM 指令从`0`开始,我们也可以用`AS`指令为阶段命令,比如我们这里的将第一阶段命名为`build-env`,然后在其他阶段需要引用的时候使用`--from=build-env`参数即可。
最后我们简单的运行下该容器测试:
```shell
$ docker run --rm -p 8080:8080 cnych/docker-multi-stage-demo:latest
```
运行成功后,我们可以在浏览器中打开`http://127.0.0.1:8080/ping`地址,可以看到**PONG**返回。
现在我们就把两个镜像的文件最终合并到一个镜像里面了。
文章中涉及到代码可以前往 github 查看:[https://github.com/cnych/docker-multi-stage-demo](https://github.com/cnych/docker-multi-stage-demo)
---
[点击查看本文视频](https://youdianzhishi.com/course/6n8xd6/)
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![k8s技术圈二维码](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 14. Kubernetes 初体验
今天开始正式进入 Kubernetes 的课程学习,Kubernetes 我们已经听过很多了,那么什么是Kubernetes呢?
## 简介
Kubernetes 是 Google 团队发起的一个开源项目,它的目标是管理跨多个主机的容器,用于自动部署、扩展和管理容器化的应用程序,主要实现语言为 Go 语言。Kubernetes 的组件和架构还是相对较复杂的,如果我们一上来就给大家讲解这些概念,可能很多同学都消化不了,所以我们先让我们的同学来使用我们的Kubernetes,去感受下,去体验下里面的一些概念和用法,等你对这些基本概念熟悉以后,再来给大家讲解Kubernetes的组件和架构应该就更加容易了。
怎样体验呢?当然最好的办法就是我们自己搭建一套集群了,但是如果完完全全都我们手动去搭建的话,第一是太耗时,第二是太复杂,可能我们现在还没有这个实力,没关系,我们可以使用一些工具来辅助我们。
1.`katacoda`的课程:[katacoda](https://www.katacoda.com/courses/kubernetes),可以在网站上帮我们启动一个minikube的环境(学习)
​​![katacoda](./images/k8s-katacoda.png)
2.需要我们自己来搭建的 - [`Rancher`](https://rancher.com/),我们之前给大家介绍过,如果你网速不好的话安装 Rancher 可能需要花费一点时间,不过这是值得的。(测试)
```shell
$ docker run -d --restart=unless-stopped -p 80:80 -p 443:443 rancher/rancher:v2.0.0 # 查看日志
$ docker logs -f rancher
```
![rancher](./images/k8s-rancher.png)
3.Docker for MAC/Windows(推荐)/[minikube](https://github.com/kubernetes/minikube)/(本地)
> Docker for MAC/Windows 和 minikube 安装之前需要安装[kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)工具
4.[kubeadm](https://k8s.qikqiak.com/docs/16.%E7%94%A8%20kubeadm%20%E6%90%AD%E5%BB%BA%E9%9B%86%E7%BE%A4%E7%8E%AF%E5%A2%83.html)(测试)
5.[二进制纯手动搭建](https://blog.qikqiak.com/post/manual-install-high-available-kubernetes-cluster/)(生产)
## 集群
集群是一组节点,这些节点可以是物理服务器或者虚拟机,在他上面安装了Kubernetes环境。
​​![k8s cluster](./images/k8s-cluster.png)
**Master 负责管理集群**, master 协调集群中的所有活动,例如调度应用程序、维护应用程序的所需状态、扩展应用程序和滚动更新。
**节点是 Kubernetes 集群中的工作机器,可以是物理机或虚拟机。**每个工作节点都有一个 kubelet,它是管理节点并与 Kubernetes Master 节点进行通信的代理。节点上还应具有处理容器操作的容器运行时,例如 [Docker](https://www.docker.com/)[rkt](https://coreos.com/rkt/)。一个 Kubernetes 工作集群至少有三个节点。
Master 管理集群,而 节点 用于托管正在运行的应用程序。
当您在 Kubernetes 上部署应用程序时,您可以告诉 master 启动应用程序容器。Master 调度容器在集群的节点上运行。 节点使用 Master 公开的 Kubernetes API 与 Master 通信。用户也可以直接使用 Kubernetes 的 API 与集群交互。
### Pod
Pod 是一组紧密关联的容器集合,它们共享 PID、IPC、Network 和 UTS namespace,是Kubernetes 调度的基本单位。Pod 的设计理念是支持多个容器在一个 Pod 中共享网络和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。
![k8s pod](./images/k8s-pod.png)
​​
在 Kubernetes 中,所有对象都使用 manifest(yaml或json)来定义,比如一个简单的 nginx 服务可以定义为 nginx.yaml,它包含一个镜像为 nginx 的容器:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
```
### Label
Label 是识别 Kubernetes 对象的标签,以 key/value 的方式附加到对象上(key最长不能超过63字节,value 可以为空,也可以是不超过253字节的字符串)。
Label 不提供唯一性,并且实际上经常是很多对象(如Pods)都使用相同的 label 来标志具体的应用。
Label 定义好后其他对象可以使用 Label Selector 来选择一组相同 label 的对象(比如Service 用 label 来选择一组 Pod)。Label Selector支持以下几种方式:
* 等式,如app=nginx和env!=production
* 集合,如env in (production, qa)
* 多个label(它们之间是AND关系),如app=nginx,env=test
### Namespace
Namespace 是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的 pods, services,deployments 等都是属于某一个 namespace 的(默认是default),而 Node, PersistentVolumes 等则不属于任何 namespace。
### Deployment
是否手动创建 Pod,如果想要创建同一个容器的多份拷贝,需要一个个分别创建出来么,能否将Pods划到逻辑组里?
Deployment 确保任意时间都有指定数量的 Pod“副本”在运行。如果为某个 Pod 创建了Deployment 并且指定3个副本,它会创建3个 Pod,并且持续监控它们。如果某个 Pod 不响应,那么 Deployment 会替换它,保持总数为3.
如果之前不响应的 Pod 恢复了,现在就有4个 Pod 了,那么 Deployment 会将其中一个终止保持总数为3。如果在运行中将副本总数改为5,Deployment 会立刻启动2个新 Pod,保证总数为5。Deployment 还支持回滚和滚动升级。
当创建 Deployment 时,需要指定两个东西:
* Pod模板:用来创建 Pod 副本的模板
* Label标签:Deployment 需要监控的 Pod 的标签。
现在已经创建了 Pod 的一些副本,那么在这些副本上如何均衡负载呢?我们需要的是 Service。
### Service
Service 是应用服务的抽象,通过 labels 为应用提供负载均衡和服务发现。匹配 labels 的Pod IP 和端口列表组成 endpoints,由 kube-proxy 负责将服务 IP 负载均衡到这些endpoints 上。
每个 Service 都会自动分配一个 cluster IP(仅在集群内部可访问的虚拟地址)和 DNS 名,其他容器可以通过该地址或 DNS 来访问服务,而不需要了解后端容器的运行。
![k8s service](./images/k8s-service.png)
---
[点击查看本文视频](https://youdianzhishi.com/course/6n8xd6/)
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![k8s技术圈二维码](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
# 15. 基本概念与组件
## 基本概念
Kubernetes 中的绝大部分概念都抽象成 Kubernetes 管理的一种资源对象,下面我们一起复习一下我们上节课遇到的一些资源对象:
* Master:Master 节点是 Kubernetes 集群的控制节点,负责整个集群的管理和控制。Master 节点上包含以下组件:
* kube-apiserver:集群控制的入口,提供 HTTP REST 服务
* kube-controller-manager:Kubernetes 集群中所有资源对象的自动化控制中心
* kube-scheduler:负责 Pod 的调度
* Node:Node 节点是 Kubernetes 集群中的工作节点,Node 上的工作负载由 Master 节点分配,工作负载主要是运行容器应用。Node 节点上包含以下组件:
* kubelet:负责 Pod 的创建、启动、监控、重启、销毁等工作,同时与 Master 节点协作,实现集群管理的基本功能。
* kube-proxy:实现 Kubernetes Service 的通信和负载均衡
* 运行容器化(Pod)应用
* Pod: Pod 是 Kubernetes 最基本的部署调度单元。每个 Pod 可以由一个或多个业务容器和一个根容器(Pause 容器)组成。一个 Pod 表示某个应用的一个实例
* ReplicaSet:是 Pod 副本的抽象,用于解决 Pod 的扩容和伸缩
* Deployment:Deployment 表示部署,在内部使用ReplicaSet 来实现。可以通过 Deployment 来生成相应的 ReplicaSet 完成 Pod 副本的创建
* Service:Service 是 Kubernetes 最重要的资源对象。Kubernetes 中的 Service 对象可以对应微服务架构中的微服务。Service 定义了服务的访问入口,服务的调用者通过这个地址访问 Service 后端的 Pod 副本实例。Service 通过 Label Selector 同后端的 Pod 副本建立关系,Deployment 保证后端Pod 副本的数量,也就是保证服务的伸缩性。
![k8s basic](./images/k8s-basic.png)
​​
Kubernetes 主要由以下几个核心组件组成:
* etcd 保存了整个集群的状态,就是一个数据库;
* apiserver 提供了资源操作的唯一入口,并提供认证、授权、访问控制、API 注册和发现等机制;
* controller manager 负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
* scheduler 负责资源的调度,按照预定的调度策略将 Pod 调度到相应的机器上;
* kubelet 负责维护容器的生命周期,同时也负责 Volume(CSI)和网络(CNI)的管理;
* Container runtime 负责镜像管理以及 Pod 和容器的真正运行(CRI);
* kube-proxy 负责为 Service 提供 cluster 内部的服务发现和负载均衡;
当然了除了上面的这些核心组件,还有一些推荐的插件:
* kube-dns 负责为整个集群提供 DNS 服务
* Ingress Controller 为服务提供外网入口
* Heapster 提供资源监控
* Dashboard 提供 GUI
## 组件通信
Kubernetes 多组件之间的通信原理:
* apiserver 负责 etcd 存储的所有操作,且只有 apiserver 才直接操作 etcd 集群
* apiserver 对内(集群中的其他组件)和对外(用户)提供统一的 REST API,其他组件均通过 apiserver 进行通信
* controller manager、scheduler、kube-proxy 和 kubelet 等均通过 apiserver watch API 监测资源变化情况,并对资源作相应的操作
* 所有需要更新资源状态的操作均通过 apiserver 的 REST API 进行
* apiserver 也会直接调用 kubelet API(如 logs, exec, attach 等),默认不校验 kubelet 证书,但可以通过 `--kubelet-certificate-authority` 开启(而 GKE 通过 SSH 隧道保护它们之间的通信)
比如最典型的创建 Pod 的流程:
​​![k8s pod](./images/k8s-pod-process.png)
* 用户通过 REST API 创建一个 Pod
* apiserver 将其写入 etcd
* scheduluer 检测到未绑定 Node 的 Pod,开始调度并更新 Pod 的 Node 绑定
* kubelet 检测到有新的 Pod 调度过来,通过 container runtime 运行该 Pod
* kubelet 通过 container runtime 取到 Pod 状态,并更新到 apiserver 中
---
[点击查看本文视频](https://youdianzhishi.com/course/6n8xd6/)
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![k8s技术圈二维码](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 17. 安装 Dashboard 插件
Kubernetes Dashboard 是 k8s集群的一个 WEB UI管理工具,代码托管在 github 上,地址:[https://github.com/kubernetes/dashboard](https://github.com/kubernetes/dashboard)
## 安装:
直接使用官方的配置文件安装即可:
```shell
$ wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
```
为了测试方便,我们将`Service`改成`NodePort`类型,注意 YAML 中最下面的 Service 部分新增一个`type=NodePort`
```yaml
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
ports:
- port: 443
targetPort: 8443
type: NodePort
selector:
k8s-app: kubernetes-dashboard
```
然后直接部署新版本的`dashboard`即可:
```shell
$ kubectl create -f kubernetes-dashboard.yaml
```
然后我们可以查看 dashboard 的外网访问端口:
```shell
$ kubectl get svc kubernetes-dashboard -n kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
haproxy ClusterIP 10.254.125.90 <none> 8440/TCP,8442/TCP 2d
kubernetes-dashboard NodePort 10.254.122.185 <none> 443:31694/TCP 10s
```
然后直接访问集群中的任何一个节点 IP 加上上面的**31694**端口即可打开 dashboard 页面了
> 由于 dashboard 默认是自建的 https 证书,该证书是不受浏览器信任的,所以我们需要强制跳转就可以了。
默认 dashboard 会跳转到登录页面,我们可以看到 dashboard 提供了`Kubeconfig``token`两种登录方式,我们可以直接跳过或者使用本地的`Kubeconfig`文件进行登录,可以看到会跳转到如下页面:
![dashboard login page](./images/dashboard-login.png)
这是由于该用户没有对`default`命名空间的访问权限。
​​
## 身份认证
登录 dashboard 的时候支持 Kubeconfig 和token 两种认证方式,Kubeconfig 中也依赖token 字段,所以生成token 这一步是必不可少的。
### 生成token
我们创建一个admin用户并授予admin 角色绑定,使用下面的yaml文件创建admin用户并赋予他管理员权限,然后就可以通过token 登陆dashbaord,这种认证方式本质实际上是通过Service Account 的身份认证加上Bearer token请求 API server 的方式实现,参考 [Kubernetes 中的认证](https://kubernetes.io/docs/admin/authentication/)
```yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kube-system
labels:
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
```
上面的`admin`用户创建完成后我们就可以获取到该用户对应的`token`了,如下命令:
```shell
$ kubectl get secret -n kube-system|grep admin-token
admin-token-d5jsg kubernetes.io/service-account-token 3 1d
$ kubectl get secret admin-token-d5jsg -o jsonpath={.data.token} -n kube-system |base64 -d# 会生成一串很长的base64后的字符串
```
然后在 dashboard 登录页面上直接使用上面得到的 token 字符串即可登录,这样就可以拥有管理员权限操作整个 kubernetes 集群的对象,当然你也可以为你的登录用户新建一个指定操作权限的用户。​​
![dashboard](./images/dashboard.png)
---
[点击查看本文视频](https://youdianzhishi.com/course/6n8xd6/)
扫描下面的二维码(或微信搜索`k8s技术圈`)关注我们的微信公众帐号,在微信公众帐号中回复 **加群** 即可加入到我们的 kubernetes 讨论群里面共同学习。
![k8s技术圈二维码](https://www.qikqiak.com/img/posts/qrcode_for_gh_d6dd87b6ceb4_430.jpg)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
jenkins-demo @ 716a8133
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册