1. 程式人生 > >centos7安裝指定版本docker和kubeadm安裝kubernetes

centos7安裝指定版本docker和kubeadm安裝kubernetes

一、事前準備

1、所有節點彼此網路互通,並且k8s-m1 SSH 登入其他節點為 passwdless,由於過程中很多會在某臺節點(k8s-m1)上以 SSH 複製與操作其他節點

2、確認所有防火牆與 SELinux 已關閉。如 CentOS:

systemctl stop firewalld && systemctl disable firewalld

setenforce 0

3、所有節點需要設定/etc/hosts解析到所有叢集主機。

4、所有節點需要設定以下系統引數。

$ cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

$ sysctl -p /etc/sysctl.d/k8s.conf

5、關閉系統 Swap,請在所有節點利用以下指令關閉:

$ swapoff -a && sysctl -w vm.swappiness=0

# 不同檔案會有差異
$ sed '/swap.img/d' -i /etc/fstab

二、安裝docker

1、刪除已安裝的Docker

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine

2、配置yum源

cd /etc/yum.repo.d/

yum clean

yum makecache

3、檢視Docker版本:

yum list docker-ce --showduplicates

4、安裝指定版本

yum install -y --setopt=obsoletes=0 \

docker-ce-17.03.2.ce-1.el7.centos.x86_64 \

docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch

啟動docker

systemctl start docker

三、安裝k8s

使用kubeadm安裝:

1.首先配置各節點阿里K8S YUM源

cat <<EOF > /etc/yum.repos.d/kubernetes.repo

[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0

EOF

yum -y install epel-release

yum clean all

yum makecache

2.在各節點安裝kubeadm和相關工具包(本文安裝的是1.10.0版本)

yum install -y kubelet-1.10.0 kubeadm-1.10.0 kubectl-1.10.0 --disableexcludes=kubernetes

3.啟動kubelet服務

systemctl enable kubelet && systemctl start kubelet

提示:此時kubelet的服務執行狀態是異常的,因為缺少主配置檔案kubelet.conf。但可以暫不處理,因為在完成Master節點的初始化後才會生成這個配置檔案。

修改kubelet配置,啟動kubelet(所有節點)

注意:時刻檢視/var/log/message的日誌輸出,會看到kubelet一直啟動失敗。

4、編輯10-kubeadm.conf的檔案,修改cgroup-driver配置:

  1. [[email protected]]# cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

  2. [Service]

  3. Environment="KUBELET_KUBECONFIG_ARGS=--kubeconfig=/etc/kubernetes/kubelet.conf --require-kubeconfig=true"

  4. Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"

  5. Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"

  6. Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"

  7. Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"

  8. Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"

  9. Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs"

  10. ExecStart=

  11. ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CGROUP_ARGS $KUBELET_EXTRA_ARGS

將“--cgroup-driver=systems”修改成為“--cgroup-driver=cgroupfs”,重新啟動kubelet。

systemctl restart kubelet

4.下載K8S相關映象(Master節點操作)

因為無法直接訪問gcr.io下載映象,所以需要配置一個國內的容器映象加速器

配置一個阿里雲的加速器:

在頁面中找到並點選映象加速按鈕,即可看到屬於自己的專屬加速連結,選擇Centos版本後即可看到配置方法。

提示:在阿里雲上使用 Docker 並配置阿里雲映象加速器,可能會遇到 daemon.json 導致 docker daemon 無法啟動的問題,可以通過以下方法解決。

你需要的是編輯 

vim /etc/sysconfig/docker 

然後 

OPTIONS='--selinux-enabled --log-driver=journald --registry-mirror=http://xxxx.mirror.aliyuncs.com' 
registry-mirror 輸入你的映象地址 

最後 service docker restart 重啟 daemon 

然後 ps aux | grep docker 然後你就會發現帶有映象的啟動引數了。

5.下載K8S相關映象

#!/bin/bash
images=(kube-proxy-amd64:v1.10.0 kube-scheduler-amd64:v1.10.0 kube-controller-manager-amd64:v1.10.0 kube-apiserver-amd64:v1.10.0
etcd-amd64:3.1.12 pause-amd64:3.1 kubernetes-dashboard-amd64:v1.8.3 k8s-dns-sidecar-amd64:1.14.8 k8s-dns-kube-dns-amd64:1.14.8
k8s-dns-dnsmasq-nanny-amd64:1.14.8)
for imageName in ${images[@]} ; do
  docker pull keveon/$imageName
  docker tag keveon/$imageName k8s.gcr.io/$imageName
  docker rmi keveon/$imageName
done

上面的shell指令碼主要做了3件事,下載各種需要用到的容器映象、重新打標記為符合k8s命令規範的版本名稱、清除舊的容器映象。

提示:映象版本一定要和kubeadm安裝的版本一致,否則會出現time out問題。

6.初始化安裝K8S Master

執行上述shell指令碼,等待下載完成後,執行kubeadm init

[[email protected] ~]# kubeadm init --kubernetes-version=v1.10.0 --pod-network-cidr=10.244.0.0/16
[init] Using Kubernetes version: v1.10.0
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
	[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
	[WARNING FileExisting-crictl]: crictl not found in system path
Suggestion: go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
[preflight] Starting the kubelet service
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [k8smaster kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.0.100.202]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated etcd/ca certificate and key.
[certificates] Generated etcd/server certificate and key.
[certificates] etcd/server serving cert is signed for DNS names [localhost] and IPs [127.0.0.1]
[certificates] Generated etcd/peer certificate and key.
[certificates] etcd/peer serving cert is signed for DNS names [k8smaster] and IPs [10.0.100.202]
[certificates] Generated etcd/healthcheck-client certificate and key.
[certificates] Generated apiserver-etcd-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"
[controlplane] Wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"
[controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
[controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"
[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"
[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests".
[init] This might take a minute or longer if the control plane images have to be pulled.
[apiclient] All control plane components are healthy after 21.001790 seconds
[uploadconfig] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[markmaster] Will mark node k8smaster as master by adding a label and a taint
[markmaster] Master k8smaster tainted and labelled with key/value: node-role.kubernetes.io/master=""
[bootstraptoken] Using token: thczis.64adx0imeuhu23xv
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: kube-dns
[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join 10.0.100.202:6443 --token thczis.64adx0imeuhu23xv --discovery-token-ca-cert-hash sha256:fa7b11bb569493fd44554aab0afe55a4c051cccc492dbdfafae6efeb6ffa80e6

提示:選項--kubernetes-version=v1.10.0是必須的,否則會因為訪問google網站被牆而無法執行命令。這裡使用v1.10.0版本,剛才前面也說到了下載的容器映象版本必須與K8S版本一致否則會出現time out。

上面的命令大約需要1分鐘的過程,期間可以觀察下tail -f /var/log/message日誌檔案的輸出,掌握該配置過程和進度。上面最後一段的輸出資訊儲存一份,後續新增工作節點還要用到。

7.配置kubectl認證資訊(Master節點操作)

# 對於非root使用者
mkdir -p $HOME/.kube

sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 對於root使用者
export KUBECONFIG=/etc/kubernetes/admin.conf

也可以直接放到~/.bash_profile

echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile

8.安裝flannel網路(Master節點操作)

mkdir -p /etc/cni/net.d/

cat <<EOF> /etc/cni/net.d/10-flannel.conf
{
“name”: “cbr0”,
“type”: “flannel”,
“delegate”: {
“isDefaultGateway”: true
}
}

EOF

mkdir /usr/share/oci-umount/oci-umount.d -p

mkdir /run/flannel/

cat <<EOF> /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.1.0/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

EOF

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml

9.讓node1、node2加入叢集

在node1和node2節點上分別執行kubeadm join命令,加入叢集:

[[email protected] ~]# kubeadm join 10.0.100.202:6443 --token thczis.64adx0imeuhu23xv --discovery-token-ca-cert-hash sha256:fa7b11bb569493fd44554aab0afe55a4c051cccc492dbdfafae6efeb6ffa80e6
[preflight] Running pre-flight checks.
	[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
	[WARNING FileExisting-crictl]: crictl not found in system path
Suggestion: go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
[discovery] Trying to connect to API Server "10.0.100.202:6443"
[discovery] Created cluster-info discovery client, requesting info from "https://10.0.100.202:6443"
[discovery] Requesting info from "https://10.0.100.202:6443" again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "10.0.100.202:6443"
[discovery] Successfully established connection with API Server "10.0.100.202:6443"

This node has joined the cluster:
* Certificate signing request was sent to master and a response
  was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the master to see this node join the cluster.

提示:細心的童鞋應該會發現,這段命令其實就是前面K8S Matser安裝成功後我讓你們儲存的那段命令。

預設情況下,Master節點不參與工作負載,但如果希望安裝出一個All-In-One的k8s環境,則可以執行以下命令,讓Master節點也成為一個Node節點:

kubectl taint nodes --all node-role.kubernetes.io/master-

10.驗證K8S Master是否搭建成功(Master節點操作)

# 檢視節點狀態
kubectl get nodes

# 檢視pods狀態
kubectl get pods --all-namespaces

# 檢視K8S叢集狀態
kubectl get cs

常見錯誤解析

安裝時候最常見的就是time out,因為K8S映象在國外,所以我們在前面就說到了提前把他下載下來,可以用一個國外機器採用habor搭建一個私有倉庫把映象都download下來。

[[email protected] ~]# kubeadm init
[init] Using Kubernetes version: v1.10.0
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
	[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
	[WARNING FileExisting-crictl]: crictl not found in system path
Suggestion: go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
[preflight] Starting the kubelet service
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [k8smaster kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.0.100.202]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated etcd/ca certificate and key.
[certificates] Generated etcd/server certificate and key.
[certificates] etcd/server serving cert is signed for DNS names [localhost] and IPs [127.0.0.1]
[certificates] Generated etcd/peer certificate and key.
[certificates] etcd/peer serving cert is signed for DNS names [k8smaster] and IPs [10.0.100.202]
[certificates] Generated etcd/healthcheck-client certificate and key.
[certificates] Generated apiserver-etcd-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"
[controlplane] Wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"
[controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
[controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"
[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"
[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests".
[init] This might take a minute or longer if the control plane images have to be pulled.

Unfortunately, an error has occurred:
	timed out waiting for the condition

This error is likely caused by:
	- The kubelet is not running
	- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
	- Either there is no internet connection, or imagePullPolicy is set to "Never",
	  so the kubelet cannot pull or find the following control plane images:
		- k8s.gcr.io/kube-apiserver-amd64:v1.10.0
		- k8s.gcr.io/kube-controller-manager-amd64:v1.10.0
		- k8s.gcr.io/kube-scheduler-amd64:v1.10.0
		- k8s.gcr.io/etcd-amd64:3.1.12 (only if no external etcd endpoints are configured)

If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
	- 'systemctl status kubelet'
	- 'journalctl -xeu kubelet'
couldn't initialize a Kubernetes cluster

那出現這個問題大部分原因是因為安裝的K8S版本和依賴的K8S相關映象版本不符導致的,關於這部分排錯可以檢視/var/log/message我們在文章開始安裝的時候也提到了要多看日誌。

還有些童鞋可能會說,那我安裝失敗了,怎麼清理環境重新安裝啊?下面教大家一條命令:

kubeadm reset

好了,至此就完成了K8S三節點叢集的安裝部署。

參考文件:

相關推薦

centos7安裝指定版本dockerkubeadm安裝kubernetes

一、事前準備 1、所有節點彼此網路互通,並且k8s-m1 SSH 登入其他節點為 passwdless,由於過程中很多會在某臺節點(k8s-m1)上以 SSH 複製與操作其他節點 2、確認所有防火牆與 SELinux 已關閉。如 CentOS: systemctl st

vue-cli 安裝,解除安裝安裝指定版本建立專案問題相關整理

vue-cli2.x.x 版本 安裝指定版本 所有版本安裝,前提是已經全域性安裝過node 和 全域性安裝過webpack npm install -g [email protected] vue-cli2.x.x 版本解除安裝 npm uninstall -

在Linux Centos 7.2 上安裝指定版本Docker 17.03

code style tps com 註意 時間 可能 mapper git https://docs.docker.com/install/linux/docker-ce/centos/#install-docker-ce   先清空下“歷史&

Centos7 安裝指定版本Docker

changelog ber build con linux c mirror mir led host Centos 安裝指定版本的 Docker 安裝kubernetes 集群,個別kubernetes對docke版本有要求,簡單整理安裝指定版本docker過程如下: k

centos7安裝指定版本mysql5.7.23

運行 blank 8.0 comm 手動 yum str 禁用 名稱 現在mysql版本已經到MySQL 8.0(GA)穩定版本了,所以需求是想簡單又快速在centos7下安裝指定版本例如MySQL 5.7(GA)版本有下面這種方法 首先需要到mysql官網這裏下載對應R

使用Docker官方yum源安裝指定版本docker的標準操作流程

解除安裝老版本的Docker,沒有安裝則不解除安裝。 yum remove docker \ docker-client \ docker-client-latest \

安裝指定版本docker

安裝 Docker 從 2017 年 3 月開始 docker 在原來的基礎上分為兩個分支版本: Docker CE 和 Docker EE。 Docker CE 即社群免費版,Docker EE 即企業版,強調安全,但需付費使用。 本文介紹 Docker CE 的安裝使用。 移除舊的版本:

Centos7通過yum安裝指定版本的PHP

1、安裝源 安裝epel-release:yum -y install epel-release  安裝yum-config-manager實用程式:yum -y install yum-utils 2、安裝PHP 選擇對應的版本進行安裝 安裝PHP5.4:yu

Ubuntu通過apt-get安裝指定版本查詢指定軟體有多少個版本

一、通過apt-get安裝指定版本apt-get install <<package name>>=<<version>>二、查詢指定軟體有多少個版本說明:在Linux用這個查詢並不能完全的把所有版本都列舉出來,因為每個版本都與系統版本和CPU架構有關,比如一個

在特定環境中安裝指定版本Docker

通常用官方提供的安裝指令碼或軟體源安裝都是安裝的比較新 Docker 版本,有時我們需要在一些特定環境的伺服器上安裝指定版本的 Docker。今天我們就來講一講如何安裝指定版本的 Docker 。 通過手動安裝 增加軟體安裝源 Ubuntu 匯入軟體倉庫證書 $ apt-key adv –key

Centos下Docker安裝指定版本

參考官網:https://www.docker.com/products/docker#/linux 一般情況下,docker安裝可以使用官網推薦的自動安裝指令碼, curl -sSL https://get.docker.com/ | sh 這樣可以安裝最新的doc

如何在ubuntu16.04版本安裝指定docker版本,阿里映象

一說明:網上安裝docker的方式都基本是通過apt-get install docker的方式安裝,但該方法安裝無法指定docker版本,受限較多。本貼選擇採用安裝deb包的方式進行二安裝策略一簡述直接下載docker的deb安裝包(CentOS為rpm包)後,安裝即可。命

使用npmcnpm分別安裝指定版本的vuejs(解決npm install安裝了太多架包的問題)

解決安裝太多架包的問題比如我需要安裝vue 1.0.28版本;指定安裝這個版本的;安裝vue 1.0.28時,執行如下命令,卻發現node_modules檔案裡猛然增加了幾十個架包,看起來非常不爽。# 只安裝Vue V1的最新版本 npm install [email&#

Docker 容器化技術介紹(九) 之 Docker 安裝指定版本安裝

開發環境為 centos 7 1 下載安裝包     在下面路徑中下載 需要的安裝包版本 (如果不能開啟,大家可以翻牆) 2 下載資料包 大家可以下載大家需要的版本,這裡下載的版本為 1.12.6 docker-engin

docker安裝指定版本TAG的鏡像

code 最新版 with sql jre mys alpine 最新 server 在docker中安裝鏡像,一般過程是,docker search 軟件名稱。 本文以tomcat為例,講解下載指定版本TAG的tomcat。 搜索tomcat鏡像 $ sudo

Ubuntu通過apt-get安裝指定版本查詢軟件源有多少個版本

bsp -c code apt-get 不能 cpu架構 pack 1.0 inux 一、通過apt-get安裝指定版本 apt-get install <<package name>>=<<version>> 二

laravel composer 安裝指定版本以及基本的配置

err ida 擴展 wap 服務層 cache ssi san ice 1 安裝指定的 laravel版本 以下的案例是安裝5.5版本 composer create-project laravel/laravel=5.5.* --prefer-dist 2 配置 優

MAC下安裝版本JDK切換幾種方式

lin 切換jdk版本 ber 方便 ida 不支持 itl 相關 pro 環境: MAC PRO,OS X 10.11.6,64位 歷史: 過去 Mac 上的 Java 都是由 Apple 自己提供,只支持到 Java 6,並且OS X 10.7 開始系統並不自帶(而

Pycharm如何安裝指定版本的模塊

圖片 分享圖片 模塊名 點擊 alt nbsp info 選擇 blog 在setting界面中,選擇Project Interpreter,點擊+號,搜索模塊名稱,在右下方可以選擇需要安裝的版本。 Pycharm如何安裝指定版本的模塊

pip 安裝指定版本軟件包

nbsp 有時 jinja 最新版本 軟件包 link 指定版本 新版 ans 默認情況下,pip 將安裝最新版本的軟件包,但有時需要獲取特定版本的安裝包,比如 jinja2 從 2.9 開始加入了 async 關鍵字,這個會導致 py2exe 報錯:Invalid Syn