learn.lianglianglee.com/专栏/Kubernetes 实践入门指南/07 容器引擎 containerd 落地实践.md.html
2022-09-06 22:30:37 +08:00

546 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>07 容器引擎 containerd 落地实践.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/Kubernetes 实践入门指南/00 为什么我们要学习 Kubernetes 技术.md.html">00 为什么我们要学习 Kubernetes 技术</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/01 重新认识 Kubernetes 的核心组件.md.html">01 重新认识 Kubernetes 的核心组件</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/02 深入理解 Kubernets 的编排对象.md.html">02 深入理解 Kubernets 的编排对象</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/03 DevOps 场景下落地 K8s 的困难分析.md.html">03 DevOps 场景下落地 K8s 的困难分析</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/04 微服务应用场景下落地 K8s 的困难分析.md.html">04 微服务应用场景下落地 K8s 的困难分析</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/05 解决 K8s 落地难题的方法论提炼.md.html">05 解决 K8s 落地难题的方法论提炼</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/06 练习篇K8s 核心实践知识掌握.md.html">06 练习篇K8s 核心实践知识掌握</a>
</li>
<li>
<a class="current-tab" href="/专栏/Kubernetes 实践入门指南/07 容器引擎 containerd 落地实践.md.html">07 容器引擎 containerd 落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/08 K8s 集群安装工具 kubeadm 的落地实践.md.html">08 K8s 集群安装工具 kubeadm 的落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/09 南北向流量组件 IPVS 的落地实践.md.html">09 南北向流量组件 IPVS 的落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/10 东西向流量组件 Calico 的落地实践.md.html">10 东西向流量组件 Calico 的落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/11 服务发现 DNS 的落地实践.md.html">11 服务发现 DNS 的落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/12 练习篇K8s 集群配置测验.md.html">12 练习篇K8s 集群配置测验</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/13 理解对方暴露服务的对象 Ingress 和 Service.md.html">13 理解对方暴露服务的对象 Ingress 和 Service</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/14 应用网关 OpenResty 对接 K8s 实践.md.html">14 应用网关 OpenResty 对接 K8s 实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/15 Service 层引流技术实践.md.html">15 Service 层引流技术实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/16 Cilium 容器网络的落地实践.md.html">16 Cilium 容器网络的落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/17 应用流量的优雅无损切换实践.md.html">17 应用流量的优雅无损切换实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/18 练习篇:应用流量无损切换技术测验.md.html">18 练习篇:应用流量无损切换技术测验</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/19 使用 Rook 构建生产可用存储环境实践.md.html">19 使用 Rook 构建生产可用存储环境实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/20 有状态应用的默认特性落地分析.md.html">20 有状态应用的默认特性落地分析</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/21 案例:分布式 MySQL 集群工具 Vitess 实践分析.md.html">21 案例:分布式 MySQL 集群工具 Vitess 实践分析</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/22 存储对象 PV、PVC、Storage Classes 的管理落地实践.md.html">22 存储对象 PV、PVC、Storage Classes 的管理落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/23 K8s 集群中存储对象灾备的落地实践.md.html">23 K8s 集群中存储对象灾备的落地实践</a>
</li>
<li>
<a href="/专栏/Kubernetes 实践入门指南/24 练习篇K8s 集群配置测验.md.html">24 练习篇K8s 集群配置测验</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>07 容器引擎 containerd 落地实践</h1>
<p>Docker 公司从 2013 年发布容器引擎 Docker 后就被全球开发者使用并不断改进它的功能。随着容器标准的建立Docker 引擎架构也从单体走向微服务结构,剥离出 dontainerd 引擎。它在整个容器技术架构中的位置如下:</p>
<p><img src="assets/62045630-d65f-11ea-b558-cd3c105f83ae.jpg" alt="png" /></p>
<p>图 6-1 containerd 架构图,版权源自 <a href="https://containerd.io/">https://containerd.io/</a></p>
<h3>containerd 使用初体验</h3>
<p>从官方仓库可以下载最新的 containerd 可执行文件,因为依赖 runc所以需要一并下载才能正常使用</p>
<pre><code class="language-bash"># 下载 containerd 二进制文件
wget -q --show-progress --https-only --timestamping \
https://github.com/opencontainers/runc/releases/download/v1.0.0-rc10/runc.amd64 \
https://github.com/containerd/containerd/releases/download/v1.3.4/containerd-1.3.4.linux-amd64.tar.gz \
https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.18.0/crictl-v1.18.0-linux-amd64.tar.gz
sudo mv runc.amd64 runc
# 安装二进制文件
tar -xvf crictl-v1.18.0-linux-amd64.tar.gz
chmod +x crictl runc
sudo cp crictl runc /usr/local/bin/
mkdir containerd
tar -xvf containerd-1.3.4.linux-amd64.tar.gz -C containerd
sudo cp containerd/bin/* /bin/
</code></pre>
<p>containerd 提供了默认的配置文件 config.toml默认放在 /etc/containerd/config.toml</p>
<pre><code class="language-toml">[plugins]
[plugins.cri.containerd]
snapshotter = &quot;overlayfs&quot;
[plugins.cri.containerd.default_runtime]
runtime_type = &quot;io.containerd.runtime.v1.linux&quot;
runtime_engine = &quot;/usr/local/bin/runc&quot;
runtime_root = &quot;&quot;
</code></pre>
<p>containerd 服务一般采用后台守护进程方式运行,在 Linux 中使用 systemd 运行:</p>
<pre><code class="language-bash"># 配置 containerd.service
sudo cat &lt;&lt;EOF | sudo tee /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target
[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity
[Install]
WantedBy=multi-user.target
EOF
#启动
sudo systemctl daemon-reload
sudo systemctl enable containerd
sudo systemctl start containerd
#配置 crictl 客户端
sudo crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock
</code></pre>
<p>至此containerd 的使用流程就体验完成了。</p>
<h3>通过客户端深入了解 containerd</h3>
<p>containerd 启动后,我们需要使用客户端命令行工具来了解下容器运行的情况。这个时候,我们手上有 2 个工具可以使用。一个是 crictl 这个是 Kubernetes 社区提供的操作容器接口标准的客户端工具,另外一个是 ctr 这是 containerd 自带的客户端工具ctr 是测试使用的工具,在日常工作中推荐使用 crictl 工具来管理容器。</p>
<p>ctr 工具运行如下:</p>
<pre><code class="language-bash"> ctr -
__
_____/ /______
/ ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/
containerd CLI
USAGE:
ctr [global options] command [command options] [arguments...]
VERSION:
v1.3.4
DESCRIPTION:
ctr is an unsupported debug and administrative client for interacting
with the containerd daemon. Because it is unsupported, the commands,
options, and operations are not guaranteed to be backward compatible or
stable from release to release of the containerd project.
COMMANDS:
plugins, plugin provides information about containerd plugins
version print the client and server versions
containers, c, container manage containers
content manage content
events, event display containerd events
images, image, i manage images
leases manage leases
namespaces, namespace, ns manage namespaces
pprof provide golang pprof outputs for containerd
run run a container
snapshots, snapshot manage snapshots
tasks, t, task manage tasks
install install a new package
shim interact with a shim directly
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--debug enable debug output in logs
--address value, -a value address for containerd's GRPC server (default: &quot;/run/contai
nerd/containerd.sock&quot;)
--timeout value total timeout for ctr commands (default: 0s)
--connect-timeout value timeout for connecting to containerd (default: 0s)
--namespace value, -n value namespace to use with commands (default: &quot;default&quot;) [$CONTA
INERD_NAMESPACE]
--help, -h show help
--version, -v print the version
</code></pre>
<p>crictl 运行命令如下:</p>
<pre><code>NAME:
crictl - client for CRI
USAGE:
crictl [global options] command [command options] [arguments...]
VERSION:
v1.18.0
COMMANDS:
attach Attach to a running container
create Create a new container
exec Run a command in a running container
version Display runtime version information
images, image, img List images
inspect Display the status of one or more containers
inspecti Return the status of one or more images
imagefsinfo Return image filesystem info
inspectp Display the status of one or more pods
logs Fetch the logs of a container
port-forward Forward local port to a pod
ps List containers
pull Pull an image from a registry
run Run a new container inside a sandbox
runp Run a new pod
rm Remove one or more containers
rmi Remove one or more images
rmp Remove one or more pods
pods List pods
start Start one or more created containers
info Display information of the container runtime
stop Stop one or more running containers
stopp Stop one or more running pods
update Update one or more running containers
config Get and set crictl options
inspecti Return the status of one or more images
imagefsinfo Return image filesystem info
inspectp Display the status of one or more pods
logs Fetch the logs of a container
port-forward Forward local port to a pod
ps List containers
pull Pull an image from a registry
run Run a new container inside a sandbox
runp Run a new pod
rm Remove one or more containers
rmi Remove one or more images
rmp Remove one or more pods
pods List pods
start Start one or more created containers
info Display information of the container runtime
stop Stop one or more running containers
stopp Stop one or more running pods
update Update one or more running containers
config Get and set crictl options
stats List container(s) resource usage statistics
completion Output shell completion code
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--config value, -c value Location of the client config file. If not specified
and the default does not exist, the program's directory is searched as well (default: &quot;/et
c/crictl.yaml&quot;) [$CRI_CONFIG_FILE]
--debug, -D Enable debug mode (default: false)
--image-endpoint value, -i value Endpoint of CRI image manager service [$IMAGE_SERVIC
E_ENDPOINT]
--runtime-endpoint value, -r value Endpoint of CRI container runtime service (default:
&quot;unix:///var/run/dockershim.sock&quot;) [$CONTAINER_RUNTIME_ENDPOINT]
--timeout value, -t value Timeout of connecting to the server (default: 2s)
--help, -h show help (default: false)
--version, -v print the version (default: false)
</code></pre>
<p>从 2 个命令参数对比参照可以得知crictl 的功能是比 ctr 要丰富很多的。为了日常使用方便,这里我把 crictl 和 Docker 命令做一个对比,方便大家参照使用:</p>
<table>
<thead>
<tr>
<th align="left">镜像相关功能</th>
<th align="left">Docker</th>
<th align="left">Containerd</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">显示本地镜像列表</td>
<td align="left">docker images</td>
<td align="left">crictl images</td>
</tr>
<tr>
<td align="left">下载镜像</td>
<td align="left">docker pull</td>
<td align="left">crictl pull</td>
</tr>
<tr>
<td align="left">上传镜像</td>
<td align="left">docker push</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">删除本地镜像</td>
<td align="left">docker rmi</td>
<td align="left">crictl rmi</td>
</tr>
<tr>
<td align="left">查看镜像详情</td>
<td align="left">docker inspect IMAGE-ID</td>
<td align="left">crictl inspecti IMAGE-ID</td>
</tr>
</tbody>
</table>
<blockquote>
<p>注意上传镜像功能属于和镜像仓库服务的交互crictl 没有提供此功能可以减轻不少代码逻辑负担。</p>
</blockquote>
<table>
<thead>
<tr>
<th align="left">容器相关功能</th>
<th align="left">Docker</th>
<th align="left">Containerd</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">显示容器列表</td>
<td align="left">docker ps</td>
<td align="left">crictl ps</td>
</tr>
<tr>
<td align="left">创建容器</td>
<td align="left">docker create</td>
<td align="left">crictl create</td>
</tr>
<tr>
<td align="left">启动容器</td>
<td align="left">docker start</td>
<td align="left">crictl start</td>
</tr>
<tr>
<td align="left">停止容器</td>
<td align="left">docker stop</td>
<td align="left">crictl stop</td>
</tr>
<tr>
<td align="left">删除容器</td>
<td align="left">docker rm</td>
<td align="left">crictl rm</td>
</tr>
<tr>
<td align="left">查看容器详情</td>
<td align="left">docker inspect</td>
<td align="left">crictl inspect</td>
</tr>
<tr>
<td align="left">attach</td>
<td align="left">docker attach</td>
<td align="left">crictl attach</td>
</tr>
<tr>
<td align="left">exec</td>
<td align="left">docker exec</td>
<td align="left">crictl exec</td>
</tr>
<tr>
<td align="left">logs</td>
<td align="left">docker logs</td>
<td align="left">crictl logs</td>
</tr>
<tr>
<td align="left">stats</td>
<td align="left">docker stats</td>
<td align="left">crictl stats</td>
</tr>
</tbody>
</table>
<p>看到以上清单cotnainerd 和 Docker 的功能是一脉相承。因此在生产环境使用 containerd 可以减少很多调用依赖。</p>
<p>Docker 作为 K8s 容器运行时,调用关系如下:</p>
<pre><code>kubelet --&gt; docker shim (在 kubelet 进程中) --&gt; dockerd --&gt; containerd
</code></pre>
<p>Containerd 作为 K8s 容器运行时,调用关系如下:</p>
<pre><code>kubelet --&gt; cri plugin在 containerd 进程中) --&gt; containerd
</code></pre>
<p>dockerd 是 Docker 原生容器应用引擎提供的代理服务,内置了 swarm cluster、docker build、docker push、docker api 等扩展功能,但是在生产环境默认都是 Kubernetes 集群环境,所以这块的功能可以直接去掉。</p>
<h3>对于 Docker 容器日志、网络配置</h3>
<p>日志对比</p>
<table>
<thead>
<tr>
<th align="left">对比项</th>
<th align="left">Docker</th>
<th align="left">Containerd</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">存储路径</td>
<td align="left">如果 Docker 作为 Kubernetes 容器运行时,容器日志的落盘将由 docker 来完成,保存在类似<code>/var/lib/docker/containers/$CONTAINERID</code> 目录下。Kubelet 会在 <code>/var/log/pods</code><code>/var/log/containers</code> 下面建立软链接,指向 <code>/var/lib/docker/containers/$CONTAINERID</code> 该目录下的容器日志文件。</td>
<td align="left">如果 Containerd 作为 Kubernetes 容器运行时, 容器日志的落盘由 Kubelet 来完成,保存至 <code>/var/log/pods/$CONTAINER_NAME</code> 目录下,同时在 <code>/var/log/containers</code> 目录下创建软链接,指向日志文件。</td>
</tr>
</tbody>
</table>
<p>CNI 网络对比</p>
<table>
<thead>
<tr>
<th align="left">对比项</th>
<th align="left">Docker</th>
<th align="left">Containerd</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">谁负责调用 CNI</td>
<td align="left">Kubelet 内部的 docker-shim</td>
<td align="left">Containerd 内置的 cri-plugincontainerd 1.1 以后)</td>
</tr>
<tr>
<td align="left">如何配置 CNI</td>
<td align="left">Kubelet 参数 <code>--cni-bin-dir</code><code>--cni-conf-dir</code></td>
<td align="left">Containerd 配置文件toml <code>[plugins.cri.cni]</code><code>bin_dir = &quot;/opt/cni/bin&quot;</code><code>conf_dir = &quot;/etc/cni/net.d&quot;</code></td>
</tr>
</tbody>
</table>
<h3>总结</h3>
<p>containerd 是 Docker 容器落地实践过程中标准化的产物,经过了全球无数企业应用场景的锤炼。所以它的稳定性是值得开发者信赖的工具。虽然当前业界对 Docker 公司的产品采取回避策略,但是 containerd 是当前最佳的生产环境的容器引擎,值得继续关注场景的使用和支持。</p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/Kubernetes 实践入门指南/06 练习篇K8s 核心实践知识掌握.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/Kubernetes 实践入门指南/08 K8s 集群安装工具 kubeadm 的落地实践.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"709972693e0f3d60","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>