` 中实现skydns后端接口,用于域名(svc)到IP(clusterIP)的转换。
540 |
541 | 宿主机上运行的dnsmasq服务配置见 `/etc/dnsmasq.d/origin-dns.conf` :
542 | 1. controller(master)节点上运行master-api,监听`0.0.0.0:8053`端口,数据来自apiserver。
543 | 2. node节点上运行skydns(同master类似,直接built-in skydns),监听`127.0.0.1:53`端口,数据同样来自apiserver,`pkg/cmd/server/start/start_allinone.go:250`
544 | 3. node节点宿主机上运行dnsmasq,监听除lo口外所有接口的:53端口。后端信息来自2。
545 |
546 | 宿主机上,对dns解析请求抓包:
547 | ```bash
548 | tcpdump -i lo port 53 -nnl
549 | ```
550 | 虽然`/etc/resolve.conf`中nameserver配置为集群网卡IP地址,但tcpdump指定抓取集群网卡时并不能抓到dns解析的报文。
551 |
552 |
553 |
554 | ## 深入OpenShift SDN网络
555 | 参考资料[理解OpenShift(3):网络之 SDN](https://www.cnblogs.com/sammyliu/p/10064450.html)
556 |
557 | 参考资料中,流程图各步骤说明:
558 | 1. cri,docker_sandbox,dockershim,执行实体origin-node
559 | 2. docker直接创建容器
560 | 3. cni pluginmanager调用openshift-sdn插件,执行实体origin-node,可执行文件openshift-sdn在/opt/cni/bin目录下
561 | 4. 请求发往cni-server,执行实体openshift-sdn pod
562 | 5. 调用ipam插件host-local(详见pkg/network/node/pod.go:497),获取ip地址和路由信息,并将这些信息直接返回给openshift-sdn插件,然后转第8步
563 | 6. 详见pkg/network/node/pod.go:497,调用m.ovs.SetUpPod(req.SandboxID, req.HostVeth, podIP, vnid)
564 | 7. 详见pkg/network/node/ovscontroller.go:267
565 | 8. openshift-sdn插件调用ip.SetHWAddrByIP和ipam.ConfigureIface设置ip地址和路由信息
566 |
567 | 各节点subnet信息(类似flanneld在etcd中保存的信息/coreos.com/network)在:
568 | ```bash
569 | [root@op-m ~]# etcdctl3 get /openshift.io/registry --prefix --keys-only
570 | /openshift.io/registry/sdnnetworks/default
571 | /openshift.io/registry/sdnsubnets/op-m
572 | /openshift.io/registry/sdnsubnets/op-s1
573 | /openshift.io/registry/sdnsubnets/op-s2
574 |
575 | [root@op-m ~]# etcdctl3 get /openshift.io/registry/sdnnetworks/default | strings
576 | /openshift.io/registry/sdnnetworks/default
577 | network.openshift.io/v1
578 | ClusterNetwork
579 | default
580 | *$bc235484-08f0-11e9-9f1d-0cda411d819b2
581 | 10.101.0.0/16
582 | 10.100.0.0/16*
583 | redhat/openshift-ovs-subnet2
584 | 10.101.0.0/16
585 | [root@op-m ~]# etcdctl3 get /openshift.io/registry/sdnsubnets/op-m | strings
586 | /openshift.io/registry/sdnsubnets/op-m
587 | network.openshift.io/v1
588 | HostSubnet
589 | op-m
590 | *$bca6bebb-08f0-11e9-9f1d-0cda411d819b2
591 | !pod.network.openshift.io/node-uid
592 | $b787a6f2-08f0-11e9-9f1d-0cda411d819bz
593 | op-m
594 | 172.25.18.233"
595 | 10.101.2.0/23
596 | ```
597 | openshift SDN根据上述信息配置各node的subnet。
598 | openshift SDN cni-server的运行目录:/run/openshift-sdn
599 |
600 | node上kubelet服务配置`/usr/bin/hyperkube kubelet --network-plugin=cni`
601 | ```bash
602 | [root@slim-m-18-233 ~]# cat /etc/cni/net.d/80-openshift-network.conf
603 | {
604 | "cniVersion": "0.2.0",
605 | "name": "openshift-sdn",
606 | "type": "openshift-sdn"
607 | }
608 | [root@slim-m-18-233 bin]# pwd
609 | /opt/cni/bin
610 | [root@slim-m-18-233 bin]# ls
611 | host-local loopback openshift-sdn
612 | ```
613 |
614 | openshift-sdn插件:
615 | 1. 通过IPAM获取IP地址并根据subnet地址生成默认添加的路由
616 | 2. 设置OVS(ovs-vsctl将infra容器主机端虚拟网卡加入br0,ovs-ofctl设置流表规则)
617 |
618 | 本节点网络信息位置`/var/lib/cni/networks/openshift-sdn`,例如
619 | ```bash
620 | [root@xu openshift-sdn]# cat 10.101.2.92
621 | 1cc6a193e9ea4320e0f6282d4eaa6701e12fa21ff361d720c03f6e1fe9d1b324
622 | ```
623 |
624 | 附使用IPAM插件host-local分配IP地址的示例:
625 | ```bash
626 | echo '{ "cniVersion": "0.3.1", "name": "examplenet", "ipam": { "type": "host-local", "ranges": [ [{"subnet": "203.0.113.0/24"}], [{"subnet": "2001:db8:1::/64"}]], "dataDir": "/tmp/cni-example" } }' | CI_COMMAND=ADD CNI_CONTAINERID=example CNI_NETNS=/dev/null CNI_IFNAME=dummy0 CNI_PATH=. ./host-local
627 | ```
628 |
629 | 进入openshift-sdn命名空间任一pod,使用如下命令查看信息:
630 | ```bash
631 | ovs-vsctl show
632 | ovs-ofctl -O OpenFlow13 dump-flows br0
633 | ovs-ofctl -O OpenFlow13 dump-tables br0
634 | ovs-ofctl -O OpenFlow13 dump-ports br0
635 | ovs-ofctl -O OpenFlow13 show br0
636 | nsenter -t <容器的PID> -n ip link
637 | iptables -t nat -s
638 | ```
639 |
640 | 为Pod设置默认路由的地方:
641 | ```golang
642 | // pkg/network/node/pod.go:112
643 |
644 | // Generates a CNI IPAM config from a given node cluster and local subnet that
645 | // CNI 'host-local' IPAM plugin will use to create an IP address lease for the
646 | // container
647 | func getIPAMConfig(clusterNetworks []common.ClusterNetwork, localSubnet string) ([]byte, error)
648 |
649 | ```
650 |
651 |
652 |
--------------------------------------------------------------------------------
/docs/performance.md:
--------------------------------------------------------------------------------
1 |
2 | * [Linux Performance](#linux-performance)
3 | * [BPF](#bpf)
4 |
5 |
6 | # Linux Performance
7 | https://www.brendangregg.com/linuxperf.html
8 |
9 | # BPF
10 | https://ebpf.io/
--------------------------------------------------------------------------------
/images/fdisk-extend-partition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ytinirt/notes/66cba70e55b46acc093cbd2ee649ada4dcaec2dc/images/fdisk-extend-partition.png
--------------------------------------------------------------------------------
/images/xfs_growfs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ytinirt/notes/66cba70e55b46acc093cbd2ee649ada4dcaec2dc/images/xfs_growfs.png
--------------------------------------------------------------------------------
/tool/gh-md-toc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | #
4 | # Steps:
5 | #
6 | # 1. Download corresponding html file for some README.md:
7 | # curl -s $1
8 | #
9 | # 2. Discard rows where no substring 'user-content-' (github's markup):
10 | # awk '/user-content-/ { ...
11 | #
12 | # 3.1 Get last number in each row like ' ... sitemap.js.*<\/h/)+2, RLENGTH-5)
21 | #
22 | # 5. Find anchor and insert it inside "(...)":
23 | # substr($0, match($0, "href=\"[^\"]+?\" ")+6, RLENGTH-8)
24 | #
25 |
26 | gh_toc_version="0.6.1"
27 |
28 | gh_user_agent="gh-md-toc v$gh_toc_version"
29 |
30 | #
31 | # Download rendered into html README.md by its url.
32 | #
33 | #
34 | gh_toc_load() {
35 | local gh_url=$1
36 |
37 | if type curl &>/dev/null; then
38 | curl --user-agent "$gh_user_agent" -s "$gh_url"
39 | elif type wget &>/dev/null; then
40 | wget --user-agent="$gh_user_agent" -qO- "$gh_url"
41 | else
42 | echo "Please, install 'curl' or 'wget' and try again."
43 | exit 1
44 | fi
45 | }
46 |
47 | #
48 | # Converts local md file into html by GitHub
49 | #
50 | # ➥ curl -X POST --data '{"text": "Hello world github/linguist#1 **cool**, and #1!"}' https://api.github.com/markdown
51 | # Hello world github/linguist#1 cool, and #1!
'"
52 | gh_toc_md2html() {
53 | local gh_file_md=$1
54 | URL=https://api.github.com/markdown/raw
55 | if [ ! -z "$GH_TOC_TOKEN" ]; then
56 | TOKEN=$GH_TOC_TOKEN
57 | else
58 | TOKEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt"
59 | fi
60 | if [ -f "$TOKEN" ]; then
61 | AUTH_HEADER=("-H" "Authorization: token $(cat $TOKEN)")
62 | fi
63 | # echo $URL 1>&2
64 | OUTPUT="$(curl -s --user-agent "$gh_user_agent" \
65 | --data-binary @"$gh_file_md" -H "Content-Type:text/plain" "${AUTH_HEADER[@]}" \
66 | $URL)"
67 |
68 | if [ "$?" != "0" ]; then
69 | echo "XXNetworkErrorXX"
70 | fi
71 | if [ "$(echo "${OUTPUT}" | awk '/API rate limit exceeded/')" != "" ]; then
72 | echo "XXRateLimitXX"
73 | else
74 | echo "${OUTPUT}"
75 | fi
76 | }
77 |
78 |
79 | #
80 | # Is passed string url
81 | #
82 | gh_is_url() {
83 | case $1 in
84 | https* | http*)
85 | echo "yes";;
86 | *)
87 | echo "no";;
88 | esac
89 | }
90 |
91 | #
92 | # TOC generator
93 | #
94 | gh_toc(){
95 | local gh_src=$1
96 | local gh_src_copy=$1
97 | local gh_ttl_docs=$2
98 | local need_replace=$3
99 |
100 | if [ "$gh_src" = "" ]; then
101 | echo "Please, enter URL or local path for a README.md"
102 | exit 1
103 | fi
104 |
105 |
106 | # Show "TOC" string only if working with one document
107 | if [ "$gh_ttl_docs" = "1" ]; then
108 |
109 | echo "Table of Contents"
110 | echo "================="
111 | echo ""
112 | gh_src_copy=""
113 |
114 | fi
115 |
116 | if [ "$(gh_is_url "$gh_src")" == "yes" ]; then
117 | gh_toc_load "$gh_src" | gh_toc_grab "$gh_src_copy"
118 | if [ "${PIPESTATUS[0]}" != "0" ]; then
119 | echo "Could not load remote document."
120 | echo "Please check your url or network connectivity"
121 | exit 1
122 | fi
123 | if [ "$need_replace" = "yes" ]; then
124 | echo
125 | echo "!! '$gh_src' is not a local file"
126 | echo "!! Can't insert the TOC into it."
127 | echo
128 | fi
129 | else
130 | local rawhtml=$(gh_toc_md2html "$gh_src")
131 | if [ "$rawhtml" == "XXNetworkErrorXX" ]; then
132 | echo "Parsing local markdown file requires access to github API"
133 | echo "Please make sure curl is installed and check your network connectivity"
134 | exit 1
135 | fi
136 | if [ "$rawhtml" == "XXRateLimitXX" ]; then
137 | echo "Parsing local markdown file requires access to github API"
138 | echo "Error: You exceeded the hourly limit. See: https://developer.github.com/v3/#rate-limiting"
139 | TOKEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt"
140 | echo "or place github auth token here: $TOKEN"
141 | exit 1
142 | fi
143 | local toc=`echo "$rawhtml" | gh_toc_grab "$gh_src_copy"`
144 | echo "$toc"
145 | if [ "$need_replace" = "yes" ]; then
146 | if grep -Fxq "" $gh_src && grep -Fxq "" $gh_src; then
147 | echo "Found markers"
148 | else
149 | echo "You don't have or in your file...exiting"
150 | exit 1
151 | fi
152 | local ts="<\!--ts-->"
153 | local te="<\!--te-->"
154 | local dt=`date +'%F_%H%M%S'`
155 | local ext=".orig.${dt}"
156 | local toc_path="${gh_src}.toc.${dt}"
157 | local toc_footer=""
158 | # http://fahdshariff.blogspot.ru/2012/12/sed-mutli-line-replacement-between-two.html
159 | # clear old TOC
160 | sed -i${ext} "/${ts}/,/${te}/{//!d;}" "$gh_src"
161 | # create toc file
162 | echo "${toc}" > "${toc_path}"
163 | echo -e "\n${toc_footer}\n" >> "$toc_path"
164 | # insert toc file
165 | if [[ "`uname`" == "Darwin" ]]; then
166 | sed -i "" "/${ts}/r ${toc_path}" "$gh_src"
167 | else
168 | sed -i "/${ts}/r ${toc_path}" "$gh_src"
169 | fi
170 | echo
171 | echo "!! TOC was added into: '$gh_src'"
172 | echo "!! Origin version of the file: '${gh_src}${ext}'"
173 | rm -f ${gh_src}${ext}
174 | echo "!! TOC added into a separate file: '${toc_path}'"
175 | rm -f ${toc_path}
176 | echo
177 | fi
178 | fi
179 | }
180 |
181 | #
182 | # Grabber of the TOC from rendered html
183 | #
184 | # $1 — a source url of document.
185 | # It's need if TOC is generated for multiple documents.
186 | #
187 | gh_toc_grab() {
188 | # if closed is on the new line, then move it on the prev line
189 | # for example:
190 | # was: The command foo1
191 | #
192 | # became: The command foo1
193 | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n<\/h/<\/h/g' |
194 | # find strings that corresponds to template
195 | grep -E -o '//g' | sed 's/<\/code>//g' |
198 | # now all rows are like:
199 | # ... .*<\/h/)+2, RLENGTH-5)
206 | href = substr($0, match($0, "href=\"[^\"]+?\"")+6, RLENGTH-7)
207 | print sprintf("%*s", level*3, " ") "* [" text "](" gh_url href ")" }' |
208 | sed 'y/+/ /; s/%/\\x/g')"
209 | }
210 |
211 | #
212 | # Returns filename only from full path or url
213 | #
214 | gh_toc_get_filename() {
215 | echo "${1##*/}"
216 | }
217 |
218 | #
219 | # Options hendlers
220 | #
221 | gh_toc_app() {
222 | local need_replace="no"
223 |
224 | if [ "$1" = '--help' ] || [ $# -eq 0 ] ; then
225 | local app_name=$(basename "$0")
226 | echo "GitHub TOC generator ($app_name): $gh_toc_version"
227 | echo ""
228 | echo "Usage:"
229 | echo " $app_name [--insert] src [src] Create TOC for a README file (url or local path)"
230 | echo " $app_name - Create TOC for markdown from STDIN"
231 | echo " $app_name --help Show help"
232 | echo " $app_name --version Show version"
233 | return
234 | fi
235 |
236 | if [ "$1" = '--version' ]; then
237 | echo "$gh_toc_version"
238 | echo
239 | echo "os: `lsb_release -d | cut -f 2`"
240 | echo "kernel: `cat /proc/version`"
241 | echo "shell: `$SHELL --version`"
242 | echo
243 | for tool in curl wget grep awk sed; do
244 | printf "%-5s: " $tool
245 | echo `$tool --version | head -n 1`
246 | done
247 | return
248 | fi
249 |
250 | if [ "$1" = "-" ]; then
251 | if [ -z "$TMPDIR" ]; then
252 | TMPDIR="/tmp"
253 | elif [ -n "$TMPDIR" -a ! -d "$TMPDIR" ]; then
254 | mkdir -p "$TMPDIR"
255 | fi
256 | local gh_tmp_md
257 | gh_tmp_md=$(mktemp $TMPDIR/tmp.XXXXXX)
258 | while read input; do
259 | echo "$input" >> "$gh_tmp_md"
260 | done
261 | gh_toc_md2html "$gh_tmp_md" | gh_toc_grab ""
262 | return
263 | fi
264 |
265 | if [ "$1" = '--insert' ]; then
266 | need_replace="yes"
267 | shift
268 | fi
269 |
270 | for md in "$@"
271 | do
272 | echo ""
273 | gh_toc "$md" "$#" "$need_replace"
274 | done
275 |
276 | echo ""
277 | echo "Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)"
278 | }
279 |
280 | #
281 | # Entry point
282 | #
283 | gh_toc_app "$@"
284 |
--------------------------------------------------------------------------------
/tool/update-toc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | TOOL_DIR=$(dirname $0)
4 | DOCS_DIR="${TOOL_DIR}/../docs"
5 |
6 | for doc in $(find ${DOCS_DIR} -name "*.md"); do
7 | ${TOOL_DIR}/gh-md-toc --insert ${doc}
8 | done
9 |
--------------------------------------------------------------------------------