Files
davidpaulyoung/public/2018/01/02/nginmesh-install/index.html
2026-05-14 14:06:21 -06:00

1073 lines
39 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>
<html lang="en-us">
<head><script src="/livereload.js?mindelay=10&amp;v=2&amp;port=1313&amp;path=livereload" data-no-instant defer></script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
(function() {
const autoTheme = false;
if (autoTheme) {
document.documentElement.setAttribute('data-auto-theme', 'true');
}
const theme = localStorage.getItem('cleanwhite-theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
document.documentElement.setAttribute('data-theme', theme);
})();
</script>
<meta property="og:site_name" content="David Young">
<meta property="og:type" content="article">
<meta property="og:image" content="http://localhost:1313/img/post-bg-2015.jpg">
<meta property="twitter:image" content="http://localhost:1313/img/post-bg-2015.jpg" />
<meta name="title" content="Nginx开源Service Mesh组件Nginmesh安装指南" />
<meta property="og:title" content="Nginx开源Service Mesh组件Nginmesh安装指南" />
<meta property="twitter:title" content="Nginx开源Service Mesh组件Nginmesh安装指南" />
<meta name="description" content="Nginmesh是NGINX的Service Mesh开源项目用于Istio服务网格平台中的数据面代理。它旨在提供七层负载均衡和服务路由功能与Istio集成作为sidecar部署并将以“标准可靠和安全的方式”使得服务间通信更容易。Nginmesh在今年底已经连续发布了0.2和0.3版本提供了服务发现请求转发路由规则性能指标收集等功能。本文介绍如何采用kubeadmin安装kubernetes集群并部署Nginmesh sidecar。">
<meta property="og:description" content="Nginmesh是NGINX的Service Mesh开源项目用于Istio服务网格平台中的数据面代理。它旨在提供七层负载均衡和服务路由功能与Istio集成作为sidecar部署并将以“标准可靠和安全的方式”使得服务间通信更容易。Nginmesh在今年底已经连续发布了0.2和0.3版本提供了服务发现请求转发路由规则性能指标收集等功能。本文介绍如何采用kubeadmin安装kubernetes集群并部署Nginmesh sidecar。" />
<meta property="twitter:description" content="Nginmesh是NGINX的Service Mesh开源项目用于Istio服务网格平台中的数据面代理。它旨在提供七层负载均衡和服务路由功能与Istio集成作为sidecar部署并将以“标准可靠和安全的方式”使得服务间通信更容易。Nginmesh在今年底已经连续发布了0.2和0.3版本提供了服务发现请求转发路由规则性能指标收集等功能。本文介绍如何采用kubeadmin安装kubernetes集群并部署Nginmesh sidecar。" />
<meta property="og:url" content="http://localhost:1313/2018/01/02/nginmesh-install/" />
<meta property="twitter:card" content="summary" />
<meta name="keyword" content="Von Balthasar, Scripture, Gravel Riding, Ham Radio, Divine Office, Open Source">
<link rel="shortcut icon" href="/img/favicon.ico">
<title>Nginx开源Service Mesh组件Nginmesh安装指南 | David Young Blog</title>
<link rel="canonical" href="/2018/01/02/nginmesh-install/">
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/hugo-theme-cleanwhite.css">
<link rel="stylesheet" href="/css/theme-variables.css">
<link rel="stylesheet" href="/css/zanshang.min.css">
<link rel="stylesheet" href="/css/font-awesome.all.min.css">
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
<script src="/js/hux-blog.min.js"></script>
<script src="/js/lazysizes.min.js"></script>
</head>
<nav class="navbar navbar-default navbar-custom navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header page-scroll">
<button type="button" class="navbar-toggle">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">David Young</a>
</div>
<div id="huxblog_navbar">
<div class="navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li>
<a href="/">All Posts</a>
</li>
<li>
<a href="/categories/life/">life</a>
</li>
<li>
<a href="/categories/tech/">tech</a>
</li>
<li>
<a href="/categories/tips/">tips</a>
</li>
<li><a href="/archive//">ARCHIVE</a></li>
<li><a href="/notes//">NOTES</a></li>
<li><a href="/about//">ABOUT</a></li>
<li>
<a href="/search"><i class="fa fa-search"></i></a>
</li>
<li>
<a href="#" id="theme-toggle" title="Toggle dark mode" style="opacity: 0;">
<i class="fa fa-moon"></i>
<i class="fa fa-sun" style="display: none;"></i>
</a>
</li>
<script>
(function() {
var theme = localStorage.getItem('cleanwhite-theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
var toggleBtn = document.getElementById('theme-toggle');
if (toggleBtn) {
var moonIcon = toggleBtn.querySelector('.fa-moon');
var sunIcon = toggleBtn.querySelector('.fa-sun');
if (theme === 'dark') {
if (moonIcon) moonIcon.style.display = 'none';
if (sunIcon) sunIcon.style.display = 'inline';
toggleBtn.setAttribute('title', 'Switch to light mode');
} else {
if (moonIcon) moonIcon.style.display = 'inline';
if (sunIcon) sunIcon.style.display = 'none';
toggleBtn.setAttribute('title', 'Switch to dark mode');
}
requestAnimationFrame(function() {
toggleBtn.style.transition = 'opacity 0.2s ease';
toggleBtn.style.opacity = '1';
});
}
})();
</script>
</ul>
</div>
</div>
</div>
</nav>
<script>
var $body = document.body;
var $toggle = document.querySelector('.navbar-toggle');
var $navbar = document.querySelector('#huxblog_navbar');
var $collapse = document.querySelector('.navbar-collapse');
$toggle.addEventListener('click', handleMagic)
function handleMagic(e){
if ($navbar.className.indexOf('in') > 0) {
$navbar.className = " ";
setTimeout(function(){
if($navbar.className.indexOf('in') < 0) {
$collapse.style.height = "0px"
}
},400)
}else{
$collapse.style.height = "auto"
$navbar.className += " in";
}
}
document.addEventListener('DOMContentLoaded', function() {
var navLinks = document.querySelectorAll('.navbar-collapse a');
navLinks.forEach(function(link) {
link.addEventListener('click', function() {
if ($navbar.className.indexOf('in') > 0) {
$navbar.className = " ";
setTimeout(function(){
if($navbar.className.indexOf('in') < 0) {
$collapse.style.height = "0px"
}
},400)
}
});
});
});
</script>
<style type="text/css">
header.intro-header {
background-image: url('/img/post-bg-2015.jpg')
}
</style>
<header class="intro-header" >
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="post-heading">
<div class="tags">
<a class="tag" href="/tags/istio" title="Istio">
Istio
</a>
<a class="tag" href="/tags/service-mesh" title="service Mesh">
service Mesh
</a>
<a class="tag" href="/tags/nginmesh" title="nginmesh">
nginmesh
</a>
</div>
<h1>Nginx开源Service Mesh组件Nginmesh安装指南</h1>
<h2 class="subheading"></h2>
<span class="meta">
Posted by
赵化冰
on
Tuesday, January 2, 2018
</span>
</div>
</div>
</div>
</div>
</header>
<article>
<div class="container">
<div class="row">
<div class="
col-lg-8 col-lg-offset-2
col-md-10 col-md-offset-1
post-container">
<h2 id="前言">前言</h2>
<p>Nginmesh是NGINX的Service Mesh开源项目用于Istio服务网格平台中的数据面代理。它旨在提供七层负载均衡和服务路由功能与Istio集成作为sidecar部署并将以“标准可靠和安全的方式”使得服务间通信更容易。Nginmesh在今年底已经连续发布了0.2和0.3版本,提供了服务发现,请求转发,路由规则,性能指标收集等功能。</p>
<p>
<img src="https://raw.githubusercontent.com/nginmesh/nginmesh/master/images/nginx_sidecar.png" alt="Nginmesh sidecar proxy">
</p>
<blockquote>
<p>备注本文安装指南基于Ubuntu 16.04在Centos上某些安装步骤的命令可能需要稍作改动。</p>
</blockquote>
<h2 id="安装kubernetes-cluster">安装Kubernetes Cluster</h2>
<p>Kubernetes Cluster包含etcd, api server, schedulercontroller manager等多个组件组件之间的配置较为复杂如果要手动去逐个安装及配置各个组件需要了解kubernetes操作系统及网络等多方面的知识对安装人员的能力要求较高。kubeadm提供了一个简便快速安装Kubernetes Cluster的方式并且可以通过安装配置文件提供较高的灵活性因此我们采用kubeadm安装kubernetes cluster。</p>
<p>首先参照<a href="https://kubernetes.io/docs/setup/independent/install-kubeadm">kubeadm的说明文档</a>在计划部署kubernetes cluster的每个节点上安装dockerkubeadm, kubelet 和 kubectl。</p>
<p>安装docker</p>
<pre tabindex="0"><code>apt-get update
apt-get install -y docker.io
</code></pre><p>使用google的源安装kubelet kubeadm和kubectl</p>
<pre tabindex="0"><code>apt-get update &amp;&amp; apt-get install -y apt-transport-https
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat &lt;&lt;EOF &gt;/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
</code></pre><p>使用kubeadmin安装kubernetes cluster</p>
<p>Nginmesh使用Kubernetes的<a href="https://kubernetes.io/docs/admin/extensible-admission-controllers/#initializers">Initializer机制</a>来实现sidecar的自动注入。Initializer目前是kubernetes的一个Alpha feature缺省是未启用的需要<a href="https://kubernetes.io/docs/admin/extensible-admission-controllers/#enable-initializers-alpha-feature">通过api server的参数</a>打开。因此我们先创建一个kubeadm-conf配置文件用于配置api server的启动参数</p>
<pre tabindex="0"><code>apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
apiServerExtraArgs:
admission-control: Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ValidatingAdmissionWebhook,ResourceQuota,DefaultTolerationSeconds,MutatingAdmissionWebhook
runtime-config: admissionregistration.k8s.io/v1alpha1
</code></pre><p>使用kubeadmin init命令创建kubernetes master节点。
可以先试用&ndash;dry-run参数验证一下配置文件。</p>
<pre tabindex="0"><code>kubeadm init --config kubeadm-conf --dry-run
</code></pre><p>如果一切正常kubeadm将提示Finished dry-running successfully. Above are the resources that would be created.</p>
<p>下面再实际执行创建命令</p>
<pre tabindex="0"><code>kubeadm init --config kubeadm-conf
</code></pre><p>kubeadm会花一点时间拉取docker image命令完成后会提示如何将一个work node加入cluster。如下所示</p>
<pre tabindex="0"><code> kubeadm join --token fffbf6.13bcb3563428cf23 10.12.5.15:6443 --discovery-token-ca-cert-hash sha256:27ad08b4cd9f02e522334979deaf09e3fae80507afde63acf88892c8b72f143f
</code></pre><blockquote>
<p>备注目前kubeadm只能支持在一个节点上安装master支持高可用的安装将在后续版本实现。kubernetes官方给出的workaround建议是定期备份 etcd 数据<a href="https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#limitations">kubeadm limitations</a></p>
</blockquote>
<p>Kubeadm并不会安装Pod需要的网络因此需要手动安装一个Pod网络这里采用的是Calico</p>
<pre tabindex="0"><code>kubectl apply -f https://docs.projectcalico.org/v2.6/getting-started/kubernetes/installation/hosted/kubeadm/1.6/calico.yaml
</code></pre><p>使用kubectl 命令检查master节点安装结果</p>
<pre tabindex="0"><code>ubuntu@kube-1:~$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/kubernetes ClusterIP 10.96.0.1 &lt;none&gt; 443/TCP 12m
</code></pre><p>在每台工作节点上执行上述kubeadm join命令即可把工作节点加入集群中。使用kubectl 命令检查cluster中的节点情况。</p>
<pre tabindex="0"><code> ubuntu@kube-1:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
kube-1 Ready master 21m v1.9.0
kube-2 Ready &lt;none&gt; 47s v1.9.0
</code></pre><h2 id="安装istio控制面和bookinfo">安装Istio控制面和Bookinfo</h2>
<p>参考<a href="https://github.com/nginmesh/nginmesh">Nginmesh文档</a>安装Istio控制面和Bookinfo
该文档的步骤清晰明确,这里不再赘述。</p>
<p>需要注意的是在Niginmesh文档中建议通过Ingress的External IP访问bookinfo应用程序。但<a href="https://kubernetes.io/docs/concepts/services-networking/service/#type-loadbalancer">Loadbalancer只在支持的云环境中才会生效</a>并且还需要进行一定的配置。如我在Openstack环境中创建的cluster则需要参照<a href="https://docs.openstack.org/magnum/ocata/dev/kubernetes-load-balancer.html">该文档</a>对Openstack进行配置后Openstack才能够支持kubernetes的Loadbalancer service。如未进行配置通过命令查看Ingress External IP一直显示为pending状态。</p>
<pre tabindex="0"><code>NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingress LoadBalancer 10.111.158.10 &lt;pending&gt; 80:32765/TCP,443:31969/TCP 11m
istio-mixer ClusterIP 10.107.135.31 &lt;none&gt; 9091/TCP,15004/TCP,9093/TCP,9094/TCP,9102/TCP,9125/UDP,42422/TCP 11m
istio-pilot ClusterIP 10.111.110.65 &lt;none&gt; 15003/TCP,443/TCP 11m
</code></pre><p>如不能配置云环境提供Loadbalancer特性, 我们可以直接使用集群中的一个节点IP:Nodeport访问Bookinfo应用程序。</p>
<pre tabindex="0"><code>http://10.12.5.31:32765/productpage
</code></pre><p>想要了解更多关于如何从集群外部进行访问的内容,可以参考<a href="http://zhaohuabing.com/2017/11/28/access-application-from-outside/">如何从外部访问Kubernetes集群中的应用</a></p>
<h2 id="查看自动注入的sidecar">查看自动注入的sidecar</h2>
<p>使用 kubectl get pod reviews-v3-5fff595d9b-zsb2q -o yaml 命令查看Bookinfo应用的reviews服务的Pod。</p>
<pre tabindex="0"><code>apiVersion: v1
kind: Pod
metadata:
annotations:
sidecar.istio.io/status: injected-version-0.2.12
creationTimestamp: 2018-01-02T02:33:36Z
generateName: reviews-v3-5fff595d9b-
labels:
app: reviews
pod-template-hash: &#34;1999151856&#34;
version: v3
name: reviews-v3-5fff595d9b-zsb2q
namespace: default
ownerReferences:
- apiVersion: extensions/v1beta1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: reviews-v3-5fff595d9b
uid: 5599688c-ef65-11e7-8be6-fa163e160c7d
resourceVersion: &#34;3757&#34;
selfLink: /api/v1/namespaces/default/pods/reviews-v3-5fff595d9b-zsb2q
uid: 559d8c6f-ef65-11e7-8be6-fa163e160c7d
spec:
containers:
- image: istio/examples-bookinfo-reviews-v3:0.2.3
imagePullPolicy: IfNotPresent
name: reviews
ports:
- containerPort: 9080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-48vxx
readOnly: true
- args:
- proxy
- sidecar
- -v
- &#34;2&#34;
- --configPath
- /etc/istio/proxy
- --binaryPath
- /usr/local/bin/envoy
- --serviceCluster
- reviews
- --drainDuration
- 45s
- --parentShutdownDuration
- 1m0s
- --discoveryAddress
- istio-pilot.istio-system:15003
- --discoveryRefreshDelay
- 1s
- --zipkinAddress
- zipkin.istio-system:9411
- --connectTimeout
- 10s
- --statsdUdpAddress
- istio-mixer.istio-system:9125
- --proxyAdminPort
- &#34;15000&#34;
- --controlPlaneAuthPolicy
- NONE
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
image: nginmesh/proxy_debug:0.2.12
imagePullPolicy: Always
name: istio-proxy
resources: {}
securityContext:
privileged: true
readOnlyRootFilesystem: false
runAsUser: 1337
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/istio/proxy
name: istio-envoy
- mountPath: /etc/certs/
name: istio-certs
readOnly: true
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-48vxx
readOnly: true
dnsPolicy: ClusterFirst
initContainers:
- args:
- -p
- &#34;15001&#34;
- -u
- &#34;1337&#34;
image: nginmesh/proxy_init:0.2.12
imagePullPolicy: Always
name: istio-init
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
privileged: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: default-token-48vxx
readOnly: true
nodeName: kube-2
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- emptyDir:
medium: Memory
name: istio-envoy
- name: istio-certs
secret:
defaultMode: 420
optional: true
secretName: istio.default
- name: default-token-48vxx
secret:
defaultMode: 420
secretName: default-token-48vxx
status:
conditions:
- lastProbeTime: null
lastTransitionTime: 2018-01-02T02:33:54Z
status: &#34;True&#34;
type: Initialized
- lastProbeTime: null
lastTransitionTime: 2018-01-02T02:36:06Z
status: &#34;True&#34;
type: Ready
- lastProbeTime: null
lastTransitionTime: 2018-01-02T02:33:36Z
status: &#34;True&#34;
type: PodScheduled
containerStatuses:
- containerID: docker://5d0c189b9dde8e14af4c8065ee5cf007508c0bb2b3c9535598d99dc49f531370
image: nginmesh/proxy_debug:0.2.12
imageID: docker-pullable://nginmesh/proxy_debug@sha256:6275934ea3a1ce5592e728717c4973ac704237b06b78966a1d50de3bc9319c71
lastState: {}
name: istio-proxy
ready: true
restartCount: 0
state:
running:
startedAt: 2018-01-02T02:36:05Z
- containerID: docker://aba3e114ac1aa87c75e969dcc1b0725696de78d3407c5341691d9db579429f28
image: istio/examples-bookinfo-reviews-v3:0.2.3
imageID: docker-pullable://istio/examples-bookinfo-reviews-v3@sha256:6e100e4805a8c10c47040ea7b66f10ad619c7e0068696032546ad3e35ad46570
lastState: {}
name: reviews
ready: true
restartCount: 0
state:
running:
startedAt: 2018-01-02T02:35:47Z
hostIP: 10.12.5.31
initContainerStatuses:
- containerID: docker://b55108625832a3205a265e8b45e5487df10276d5ae35af572ea4f30583933c1f
image: nginmesh/proxy_init:0.2.12
imageID: docker-pullable://nginmesh/proxy_init@sha256:f73b68839f6ac1596d6286ca498e4478b8fcfa834e4884418d23f9f625cbe5f5
lastState: {}
name: istio-init
ready: true
restartCount: 0
state:
terminated:
containerID: docker://b55108625832a3205a265e8b45e5487df10276d5ae35af572ea4f30583933c1f
exitCode: 0
finishedAt: 2018-01-02T02:33:53Z
reason: Completed
startedAt: 2018-01-02T02:33:53Z
phase: Running
podIP: 192.168.79.138
qosClass: BestEffort
startTime: 2018-01-02T02:33:39Z
</code></pre><p>该命令行输出的内容相当长我们可以看到Pod中注入了一个 nginmesh/proxy_debug container,还增加了一个initContainer nginmesh/proxy_init。这两个容器是通过kubernetes initializer自动注入到pod中的。这两个container分别有什么作用呢让我们看一下<a href="https://github.com/nginmesh/nginmesh/tree/49cd69a61d7d330685ef39ccd63fac06421c3da2/istio/agent">Nginmesh源代码中的说明</a></p>
<ul>
<li>
<p>proxy_debug, which comes with the agent and NGINX.</p>
</li>
<li>
<p>proxy_init, which is used for configuring iptables rules for transparently injecting an NGINX proxy from the proxy_debug image into an application pod.</p>
</li>
</ul>
<p>proxy_debug就是sidecar代理proxy_init则用于配置iptable 规则以将应用的流量导入到sidecar代理中。</p>
<p>查看proxy_init的Dockerfile文件可以看到proxy_init其实是调用了<a href="https://github.com/nginmesh/nginmesh/blob/49cd69a61d7d330685ef39ccd63fac06421c3da2/istio/agent/docker-init/prepare_proxy.sh">prepare_proxy.sh</a>这个脚本来创建iptable规则。</p>
<p>proxy_debug Dockerfile</p>
<pre tabindex="0"><code>FROM debian:stretch-slim
RUN apt-get update &amp;&amp; apt-get install -y iptables
ADD prepare_proxy.sh /
ENTRYPOINT [&#34;/prepare_proxy.sh&#34;]
</code></pre><p>prepare_proxy.sh节选</p>
<pre tabindex="0"><code>...omitted for brevity
# Create a new chain for redirecting inbound and outbound traffic to
# the common Envoy port.
iptables -t nat -N ISTIO_REDIRECT -m comment --comment &#34;istio/redirect-common-chain&#34;
iptables -t nat -A ISTIO_REDIRECT -p tcp -j REDIRECT --to-port ${ENVOY_PORT} -m comment --comment &#34;istio/redirect-to-envoy-port&#34;
# Redirect all inbound traffic to Envoy.
iptables -t nat -A PREROUTING -j ISTIO_REDIRECT -m comment --comment &#34;istio/install-istio-prerouting&#34;
# Create a new chain for selectively redirecting outbound packets to
# Envoy.
iptables -t nat -N ISTIO_OUTPUT -m comment --comment &#34;istio/common-output-chain&#34;
...omitted for brevity
</code></pre><h2 id="关联阅读">关联阅读</h2>
<p><a href="http://zhaohuabing.com/2017/11/04/istio-install_and_example/">Istio及Bookinfo示例程序安装试用笔记</a></p>
<h2 id="参考">参考</h2>
<ul>
<li>
<p><a href="https://github.com/nginmesh/nginmesh/">Service Mesh with Istio and NGINX</a></p>
</li>
<li>
<p><a href="https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/#14-installing-kubeadm-on-your-hosts">Using kubeadm to Create a Cluster</a></p>
</li>
<li>
<p><a href="https://kubernetes.io/docs/admin/extensible-admission-controllers/#enable-initializers-alpha-feature">Kubernetes Reference Documentation-Dynamic Admission Control</a></p>
</li>
</ul>
<div class="entry-shang text-center">
<p>「真诚赞赏,手留余香」</p>
<button class="zs show-zs btn btn-bred">赞赏支持</button>
</div>
<div class="zs-modal-bg"></div>
<div class="zs-modal-box">
<div class="zs-modal-head">
<button type="button" class="close">×</button>
<span class="author"><a href="http://localhost:1313/"><img src="/img/favicon.png" />David Young</a></span>
<p class="tip"><i></i><span>真诚赞赏,手留余香</span></p>
</div>
<div class="zs-modal-body">
<div class="zs-modal-btns">
<button class="btn btn-blink" data-num="2">2元</button>
<button class="btn btn-blink" data-num="5">5元</button>
<button class="btn btn-blink" data-num="10">10元</button>
<button class="btn btn-blink" data-num="50">50元</button>
<button class="btn btn-blink" data-num="100">100元</button>
<button class="btn btn-blink" data-num="1">任意金额</button>
</div>
<div class="zs-modal-pay">
<button class="btn btn-bred" id="pay-text">2元</button>
<p>使用<span id="pay-type">微信</span>扫描二维码完成支付</p>
<img src="/img/reward/wechat-2.png" id="pay-image"/>
</div>
</div>
<div class="zs-modal-footer">
<label><input type="radio" name="zs-type" value="wechat" class="zs-type" checked="checked"><span ><span class="zs-wechat"><img src="/img/reward/wechat-btn.png"/></span></label>
<label><input type="radio" name="zs-type" value="alipay" class="zs-type" class="zs-alipay"><img src="/img/reward/alipay-btn.png"/></span></label>
</div>
</div>
<script type="text/javascript" src="/js/reward.js"></script>
<hr>
<ul class="pager">
<li class="previous">
<a href="/2017/11/28/access-application-from-outside/" data-toggle="tooltip" data-placement="top" title="如何从外部访问Kubernetes集群中的应用">&larr;
Previous Post</a>
</li>
<li class="next">
<a href="/2018/05/22/user_authentication_authorization/" data-toggle="tooltip" data-placement="top" title="如何构建安全的微服务应用?">Next
Post &rarr;</a>
</li>
</ul>
<link href="https://xxx.xxx.com/dist/Artalk.css" rel="stylesheet" />
<script src="https://xxx.xxx.com/dist/Artalk.js"></script>
<div id="Comments"></div>
<script>
Artalk.init({
el: '#Comments',
pageKey: 'http:\/\/localhost:1313\/2018\/01\/02\/nginmesh-install\/',
pageTitle: 'Nginx开源Service Mesh组件Nginmesh安装指南',
server: 'https:\/\/xxx.xxx.com',
site: 'xxx blog',
})
</script>
</div>
<div class="
col-lg-2 col-lg-offset-0
visible-lg-block
sidebar-container
catalog-container">
<div class="side-catalog">
<hr class="hidden-sm hidden-xs">
<h5>
<a class="catalog-toggle" href="#">CATALOG</a>
</h5>
<ul class="catalog-body"></ul>
</div>
</div>
<div class="
col-lg-8 col-lg-offset-2
col-md-10 col-md-offset-1
sidebar-container">
<section>
<hr class="hidden-sm hidden-xs">
<h5><a href="/tags/">FEATURED TAGS</a></h5>
<div class="tags">
<a href="/tags/docker" title="docker">
docker
</a>
<a href="/tags/istio" title="istio">
istio
</a>
<a href="/tags/kubernetes" title="kubernetes">
kubernetes
</a>
<a href="/tags/microservice" title="microservice">
microservice
</a>
<a href="/tags/security" title="security">
security
</a>
<a href="/tags/service-mesh" title="service mesh">
service mesh
</a>
<a href="/tags/tips" title="tips">
tips
</a>
</div>
</section>
<section>
<hr>
<h5>FRIENDS</h5>
<ul class="list-inline">
<li><a target="_blank" href="https://zhaozhihan.com">Linda的博客</a></li>
</ul>
</section>
</div>
</div>
</div>
</article>
<footer>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<ul class="list-inline text-center">
<li>
<a href="mailto:youremail@gmail.com">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fas fa-envelope fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li>
<a target="_blank" href="/your%20wechat%20qr%20code%20image">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-weixin fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li>
<a target="_blank" href="https://github.com/yourgithub">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-github fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li>
<a target="_blank" href="https://www.linkedin.com/in/yourlinkedinid">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-linkedin fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li>
<a target="_blank" href="https://stackoverflow.com/users/yourstackoverflowid">
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fab fa-stack-overflow fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
<li>
<a href='' rel="alternate" type="application/rss+xml" title="David Young" >
<span class="fa-stack fa-lg">
<i class="fas fa-circle fa-stack-2x"></i>
<i class="fas fa-rss fa-stack-1x fa-inverse"></i>
</span>
</a>
</li>
</ul>
<p class="copyright text-muted">
Copyright &copy; David Young 2026
<br>
<a href="https://themes.gohugo.io/hugo-theme-cleanwhite">CleanWhite Hugo Theme</a> by <a href="https://zhaohuabing.com">Huabing</a> |
<iframe
style="margin-left: 2px; margin-bottom:-5px;"
frameborder="0" scrolling="0" width="100px" height="20px"
src="https://ghbtns.com/github-btn.html?user=zhaohuabing&repo=hugo-theme-cleanwhite&type=star&count=true" >
</iframe>
</p>
</div>
</div>
</div>
</footer>
<script>
function loadAsync(u, c) {
var d = document, t = 'script',
o = d.createElement(t),
s = d.getElementsByTagName(t)[0];
o.src = u;
if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
s.parentNode.insertBefore(o, s);
}
</script>
<script>
if($('#tag_cloud').length !== 0){
loadAsync("/js/jquery.tagcloud.js",function(){
$.fn.tagcloud.defaults = {
color: {start: '#bbbbee', end: '#0085a1'},
};
$('#tag_cloud a').tagcloud();
})
}
</script>
<script>
(function() {
function updateTagcloudColors() {
const isDark = document.documentElement.getAttribute('data-theme') === 'dark';
const startColor = isDark ? '#808080' : '#bbbbee';
if($('#tag_cloud').length !== 0 && $.fn.tagcloud) {
$.fn.tagcloud.defaults = {
color: {start: startColor, end: '#0085a1'},
};
$('#tag_cloud a').tagcloud();
}
}
$(document).ready(function() {
updateTagcloudColors();
});
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.attributeName === 'data-theme') {
updateTagcloudColors();
}
});
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-theme']
});
})();
</script>
<script>
loadAsync("https://cdn.jsdelivr.net/npm/fastclick@1.0.6/lib/fastclick.min.js", function(){
var $nav = document.querySelector("nav");
if($nav) FastClick.attach($nav);
})
</script>
<script src="/js/theme-toggle.js"></script>
<script type="text/javascript">
function generateCatalog(selector) {
_containerSelector = 'div.post-container'
var P = $(_containerSelector), a, n, t, l, i, c;
a = P.find('h1,h2,h3,h4,h5,h6');
$(selector).html('')
a.each(function () {
n = $(this).prop('tagName').toLowerCase();
i = "#" + $(this).prop('id');
t = $(this).text();
c = $('<a href="' + i + '" rel="nofollow" title="' + t + '">' + t + '</a>');
l = $('<li class="' + n + '_nav"></li>').append(c);
$(selector).append(l);
});
return true;
}
generateCatalog(".catalog-body");
$(".catalog-toggle").click((function (e) {
e.preventDefault();
$('.side-catalog').toggleClass("fold")
}))
loadAsync("\/js\/jquery.nav.js", function () {
$('.catalog-body').onePageNav({
currentClass: "active",
changeHash: !1,
easing: "swing",
filter: "",
scrollSpeed: 700,
scrollOffset: 0,
scrollThreshold: .2,
begin: null,
end: null,
scrollChange: null,
padding: 80
});
});
</script>
</body>
</html>