├── .gitattributes ├── scripts ├── bin │ ├── certs │ │ ├── cfssl │ │ ├── hosts │ │ └── cfssljson │ ├── etcd_v3.3.13 │ │ ├── etcd │ │ └── etcdctl │ ├── extra │ │ └── bash-completion │ ├── kubernetes_v1.14.0 │ │ ├── kubectl │ │ ├── kubelet │ │ ├── kube-proxy │ │ ├── kube-apiserver │ │ ├── kube-scheduler │ │ └── kube-controller-manager │ ├── docker-ce-18.06.1.ce │ │ ├── docker │ │ ├── dockerd │ │ ├── docker-init │ │ ├── docker-proxy │ │ ├── docker-runc │ │ ├── docker-containerd │ │ ├── docker-containerd-ctr │ │ └── docker-containerd-shim │ └── README.md ├── deploy │ ├── hosts_env │ ├── deploy_coredns.sh │ ├── config.sh │ ├── base_env_01.sh │ ├── deploy_docker.sh │ ├── deploy_calico.sh │ ├── deploy_kube_proxy.sh │ ├── deploy.sh │ ├── deploy_kubelet.sh │ └── deploy_etcd.sh ├── remove │ ├── remove_node.sh │ ├── remove_master.sh │ └── remove_etcd.sh ├── images │ └── README.md ├── certs │ ├── master │ │ ├── ca-config.json │ │ ├── ca-csr.json │ │ ├── admin-csr.json │ │ ├── kube-apiserver-csr.json │ │ ├── kubelet-csr.json │ │ ├── service-account-csr.json │ │ ├── kube-proxy-csr.json │ │ ├── kube-scheduler-csr.json │ │ ├── apiserver-kubelet-client-csr.json │ │ ├── kube-controller-manager-csr.json │ │ └── gen_cert.sh │ ├── node │ │ ├── ca-config.json │ │ ├── kubelet-csr.json │ │ ├── kube-proxy-csr.json │ │ └── gen_cert.sh │ └── etcd │ │ ├── server.json │ │ ├── etcd-root-ca-csr.json │ │ ├── gen_cert.sh │ │ └── ca-config.json ├── config │ ├── master │ │ ├── scheduler │ │ ├── controller-manager │ │ ├── config │ │ └── apiserver │ ├── node │ │ ├── kube-proxy │ │ ├── config.yaml │ │ ├── config │ │ └── kubelet │ └── etcd │ │ └── etcd.conf ├── test │ └── create_cluster.sh ├── systemd │ ├── kube-scheduler.service │ ├── kube-proxy.service │ ├── kube-controller-manager.service │ ├── etcd.service │ ├── kubelet.service │ ├── kube-apiserver.service │ └── docker.service ├── README.md └── kubeconfig │ └── generate_node_kubeconfig.sh ├── images └── base │ ├── version │ ├── systemd │ └── kubelet.service │ ├── Dockerfile │ └── kubeadm.conf ├── ansible ├── roles │ └── kubernetes │ │ ├── preinstall │ │ ├── default │ │ │ └── main.yml │ │ └── tasks │ │ │ ├── main.yml │ │ │ └── 0010-swapoff.yml │ │ ├── etcd │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── master │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ ├── node │ │ ├── defaults │ │ │ └── main.yml │ │ └── tasks │ │ │ └── main.yml │ │ └── remove-node │ │ ├── defaults │ │ └── main.yml │ │ └── tasks │ │ └── main.yml ├── inventory │ └── production │ │ ├── host.ini │ │ ├── hosts.yaml │ │ ├── host.yaml-bak │ │ └── group_vars │ │ └── all.yml ├── etcd.yml ├── remove-node.yml ├── scaledown-node.yml ├── scaleup-node.yml ├── node.yml ├── master.yml ├── terminating.yml └── ansible.cfg ├── pkg ├── apis │ └── ecs │ │ ├── register.go │ │ └── v1 │ │ ├── doc.go │ │ └── register.go ├── internal │ ├── cluster │ │ ├── create │ │ │ ├── validate.go │ │ │ ├── types │ │ │ │ └── types.go │ │ │ ├── images.go │ │ │ └── actions │ │ │ │ ├── action.go │ │ │ │ ├── waitforready │ │ │ │ └── waitforready.go │ │ │ │ └── installcni │ │ │ │ └── cni.go │ │ ├── delete │ │ │ └── delete.go │ │ ├── kubeadm │ │ │ └── const.go │ │ └── context │ │ │ └── context.go │ ├── util │ │ └── env │ │ │ └── term.go │ └── apis │ │ └── config │ │ └── encoding │ │ └── scheme.go ├── client │ ├── clientset │ │ └── versioned │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── register.go │ │ │ └── clientset_generated.go │ │ │ ├── typed │ │ │ └── ecs │ │ │ │ └── v1 │ │ │ │ ├── doc.go │ │ │ │ ├── fake │ │ │ │ ├── doc.go │ │ │ │ └── fake_ecs_client.go │ │ │ │ ├── generated_expansion.go │ │ │ │ └── ecs_client.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── clientset.go │ ├── listers │ │ └── ecs │ │ │ └── v1 │ │ │ └── expansion_generated.go │ └── informers │ │ └── externalversions │ │ ├── internalinterfaces │ │ └── factory_interfaces.go │ │ ├── ecs │ │ ├── interface.go │ │ └── v1 │ │ │ └── interface.go │ │ └── generic.go ├── types │ ├── installer.go │ ├── precheck.go │ ├── ansible.go │ └── ecsclient.go ├── utils │ ├── valid_base64.go │ ├── pointer │ │ ├── pointer.go │ │ └── pointer_test.go │ └── signals │ │ └── signals.go ├── sshserver │ ├── interface.go │ ├── sftp.go │ └── sftp_test.go ├── test │ └── gen.sh ├── installer │ ├── cluster │ │ ├── nodes │ │ │ ├── command.go │ │ │ ├── role.go │ │ │ └── systemd.go │ │ ├── constants │ │ │ └── constants.go │ │ └── context.go │ ├── grpc │ │ ├── server │ │ │ ├── util.go │ │ │ └── install.go │ │ └── agent │ │ │ ├── server_test.go │ │ │ └── util.go │ ├── ssh │ │ ├── ssh.go │ │ ├── batchjob_test.go │ │ ├── configmap.go │ │ └── job_ttl.go │ └── interface.go ├── precheck │ └── interface.go ├── server │ ├── service │ │ ├── valid.go │ │ ├── interface.go │ │ └── logs.go │ ├── controller │ │ └── controller.go │ ├── middleware │ │ └── auth.go │ └── serving.go ├── container │ └── docker │ │ ├── cp.go │ │ ├── pull.go │ │ ├── run.go │ │ └── exec.go ├── kuberesource │ ├── configmap.go │ └── resourcelock.go ├── exec │ └── local.go ├── controller │ └── cluster_precheck_test.go └── enum │ └── task.go ├── doc └── images │ └── image-20190805195135765.png ├── test ├── get_logs.sh ├── delete_ecs.sh ├── scale_up.sh ├── scale_down.sh ├── create_callback.sh ├── delete_callback.sh ├── scale_up_callback.sh └── create_ecs.sh ├── configs ├── installer │ └── grpc │ │ └── agent │ │ └── agent.service ├── kube-operator │ └── check_k8s.sh └── ansible │ └── ansibleinit.toml ├── .gitignore ├── deploy ├── cr │ └── ecs_v1_kubernetescluster_cr.yaml ├── kube-operator.yaml ├── role.yaml └── ecs_v1_kubernetescluster_crd.yaml ├── main.go ├── go.mod ├── cmd └── installer │ └── grpc │ ├── agent │ ├── main.go │ └── app │ │ └── app.go │ └── server │ └── main.go ├── .travis.yml ├── Makefile └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts/bin/certs/cfssl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/certs/hosts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/base/version: -------------------------------------------------------------------------------- 1 | v1.15.3 -------------------------------------------------------------------------------- /scripts/bin/certs/cfssljson: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/etcd_v3.3.13/etcd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/etcd_v3.3.13/etcdctl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/extra/bash-completion: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/kubernetes_v1.14.0/kubectl: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/kubernetes_v1.14.0/kubelet: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/dockerd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/kubernetes_v1.14.0/kube-proxy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker-init: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker-proxy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker-runc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/kubernetes_v1.14.0/kube-apiserver: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/kubernetes_v1.14.0/kube-scheduler: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/kubernetes/preinstall/default/main.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker-containerd: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker-containerd-ctr: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/docker-ce-18.06.1.ce/docker-containerd-shim: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scripts/bin/kubernetes_v1.14.0/kube-controller-manager: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible/roles/kubernetes/etcd/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore_assert_errors: true 3 | -------------------------------------------------------------------------------- /ansible/roles/kubernetes/master/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore_assert_errors: true 3 | -------------------------------------------------------------------------------- /ansible/roles/kubernetes/node/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore_assert_errors: true 3 | -------------------------------------------------------------------------------- /ansible/roles/kubernetes/remove-node/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore_assert_errors: true 3 | -------------------------------------------------------------------------------- /pkg/apis/ecs/register.go: -------------------------------------------------------------------------------- 1 | package ecs 2 | 3 | const ( 4 | GroupName = "ecs.yun.com" 5 | ) 6 | -------------------------------------------------------------------------------- /doc/images/image-20190805195135765.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gosoon/kubernetes-operator/HEAD/doc/images/image-20190805195135765.png -------------------------------------------------------------------------------- /ansible/roles/kubernetes/preinstall/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Disable swap 3 | - import_tasks: 0010-swapoff.yml 4 | when: 5 | - disable_swap 6 | -------------------------------------------------------------------------------- /pkg/apis/ecs/v1/doc.go: -------------------------------------------------------------------------------- 1 | // Package v1 contains API Schema definitions for the ecs v1 API group 2 | // +k8s:deepcopy-gen=package,register 3 | // +groupName=ecs.yun.com 4 | package v1 5 | -------------------------------------------------------------------------------- /test/get_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | region="default" 4 | name="test-cluster" 5 | 6 | curl -s -XGET -d "${request_body}" \ 7 | http://127.0.0.1:8080/api/v1/region/${region}/cluster/${name}/logs 8 | -------------------------------------------------------------------------------- /scripts/deploy/hosts_env: -------------------------------------------------------------------------------- 1 | MASTER_HOSTS="192.168.72.81" 2 | ETCD_HOSTS="192.168.73.150,192.168.72.81" 3 | CLUSTER_NAMESPACE="default" 4 | CLUSTER_NAME="test-cluster" 5 | NODE_HOSTS="192.168.72.81,192.168.73.150" 6 | MASTER_VIP="192.168.72.81" 7 | OPERATION="creating" 8 | -------------------------------------------------------------------------------- /scripts/bin/README.md: -------------------------------------------------------------------------------- 1 | Since the files are too large, here are the mock files.If you need to use these file in this directory,please to [https://github.com/gosoon/kubernetes-utils/tree/master/scripts/bin](https://github.com/gosoon/kubernetes-utils/tree/master/scripts/bin) 2 | -------------------------------------------------------------------------------- /scripts/remove/remove_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | systemctl stop docker kubelet kube-proxy 4 | rm -f /usr/bin/{kubelet,kube-proxy} 5 | rm -rf /var/lib/kubelet/ 6 | rm -rf /usr/lib/systemd/system/kubelet.service.d/ 7 | rm -rf /etc/kubernetes/ 8 | rm -f /var/log/deploy_node.log 9 | -------------------------------------------------------------------------------- /ansible/inventory/production/host.ini: -------------------------------------------------------------------------------- 1 | [all] 2 | node1 ansible_host=192.168.75.32 ansible_user=root ip=192.168.75.32 etcd_member_name=node1 3 | node2 ansible_host=192.168.75.32 ansible_user=root ip=192.168.75.32 4 | 5 | [kube-node] 6 | node1 7 | 8 | [kube-master] 9 | node1 10 | -------------------------------------------------------------------------------- /scripts/images/README.md: -------------------------------------------------------------------------------- 1 | Since the files are too large, here are the mock files.If you need to use these file in this directory,please to [https://github.com/gosoon/kubernetes-utils/tree/master/scripts/images](https://github.com/gosoon/kubernetes-utils/tree/master/scripts/images) 2 | -------------------------------------------------------------------------------- /scripts/remove/remove_master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | systemctl stop kube-apiserver kube-controller-manager kube-scheduler 4 | rm -f /usr/bin/{kube-apiserver,kube-controller-manager,kube-schedule,kubectl} 5 | rm -rf /etc/kubernetes/ 6 | rm -rf /root/.kube/ 7 | rm -f /var/log/deploy_master.log 8 | rm -rf /var/log/kubernetes/ 9 | -------------------------------------------------------------------------------- /scripts/certs/master/ca-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "8760h" 5 | }, 6 | "profiles": { 7 | "kubernetes": { 8 | "usages": ["signing", "key encipherment", "server auth", "client auth"], 9 | "expiry": "8760h" 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /scripts/certs/node/ca-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "8760h" 5 | }, 6 | "profiles": { 7 | "kubernetes": { 8 | "usages": ["signing", "key encipherment", "server auth", "client auth"], 9 | "expiry": "8760h" 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /scripts/certs/master/ca-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "Kubernetes", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "Kubernetes", 12 | "OU": "Shanghai", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /scripts/certs/master/admin-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "admin", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:masters", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /configs/installer/grpc/agent/agent.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=kubernetes-opeartor grpc installer agent service 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/usr/bin/installer-agent 7 | Restart=on-failure 8 | RestartSec=5 9 | Type=notify 10 | LimitNOFILE=65536 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /scripts/certs/master/kube-apiserver-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "kubernetes", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "Kubernetes", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /scripts/certs/node/kubelet-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:node:10.0.2.15", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:nodes", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /scripts/config/master/scheduler: -------------------------------------------------------------------------------- 1 | ### 2 | # The following values are used to configure the kubernetes scheduler 3 | 4 | # defaults from config and scheduler should be adequate 5 | 6 | # Add your own! 7 | KUBE_SCHEDULER_ARGS="--bind-address=127.0.0.1 \ 8 | --kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \ 9 | --leader-elect=true" 10 | -------------------------------------------------------------------------------- /scripts/certs/master/kubelet-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:node:", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:nodes", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /scripts/certs/master/service-account-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "service-accounts", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "Kubernetes", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /scripts/remove/remove_etcd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e ../deploy/config.sh ] && . ../deploy/config.sh || exit 4 | 5 | CONFIG_DIR="/etc/etcd" 6 | source ${CONFIG_DIR}/etcd.conf 7 | 8 | systemctl stop etcd 9 | userdel etcd 10 | rm -f /usr/bin/etcd 11 | rm -rf ${ETCD_DATA_DIR} 12 | rm -rf ${CONFIG_DIR} 13 | rm -f /var/log/deploy_etcd.log 14 | -------------------------------------------------------------------------------- /scripts/certs/master/kube-proxy-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kube-proxy", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:node-proxier", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /scripts/certs/node/kube-proxy-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kube-proxy", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:node-proxier", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /ansible/roles/kubernetes/remove-node/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Copy private key 3 | copy: 4 | src: /home/kubernetes-operator/private-key 5 | dest: /home/kubernetes-operator/private-key 6 | force: yes 7 | 8 | - name: remove node 9 | command: bash remove_node.sh 10 | args: 11 | chdir: /home/kube/kubernetes-operator/scripts/remove 12 | -------------------------------------------------------------------------------- /scripts/certs/master/kube-scheduler-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kube-scheduler", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:kube-scheduler", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> Go 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | 9 | # Test binary, build with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # log 16 | *.log 17 | logs/ 18 | log/ 19 | output/ 20 | 21 | # other 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /scripts/certs/etcd/server.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": { 3 | "algo": "rsa", 4 | "size": 2048 5 | }, 6 | "names": [ 7 | { 8 | "O": "etcd", 9 | "OU": "etcd Security", 10 | "L": "Beijing", 11 | "ST": "Beijing", 12 | "C": "CN" 13 | } 14 | ], 15 | "CN": "etcd" 16 | } 17 | -------------------------------------------------------------------------------- /scripts/certs/master/apiserver-kubelet-client-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kubelet-api-admin", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:masters", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /images/base/systemd/kubelet.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=kubelet: The Kubernetes Node Agent 3 | Documentation=http://kubernetes.io/docs/ 4 | 5 | [Service] 6 | ExecStart=/usr/bin/kubelet 7 | Restart=always 8 | StartLimitInterval=0 9 | # NOTE: kind deviates from upstream here with a lower RestartSecuse 10 | RestartSec=1s 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /scripts/certs/master/kube-controller-manager-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "system:kube-controller-manager", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 2048 6 | }, 7 | "names": [ 8 | { 9 | "C": "China", 10 | "L": "Shanghai", 11 | "O": "system:kube-controller-manager", 12 | "OU": "Kubernetes", 13 | "ST": "Shanghai" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /configs/kube-operator/check_k8s.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kernel_num_1=$(uname -r | awk -F '.' '{print $1}') 4 | kernel_num_2=$(uname -r | awk -F '.' '{print $2}') 5 | if [ ${kernel_num_1} -lt 3 ];then 6 | echo "kernel version is minor < 3.0" 7 | exit 1 8 | fi 9 | 10 | if [ ${kernel_num_1} -eq 3 -a ${kernel_num_2} -lt 10 ];then 11 | echo "kernel version is minor < 3.10" 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /scripts/certs/etcd/etcd-root-ca-csr.json: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "etcd-root-ca", 3 | "key": { 4 | "algo": "rsa", 5 | "size": 4096 6 | }, 7 | "names": [ 8 | { 9 | "O": "etcd", 10 | "OU": "etcd Security", 11 | "L": "Beijing", 12 | "ST": "Beijing", 13 | "C": "CN" 14 | } 15 | ], 16 | "ca": { 17 | "expiry": "87600h" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /deploy/cr/ecs_v1_kubernetescluster_cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: ecs.yun.com/v1 2 | kind: KubernetesCluster 3 | metadata: 4 | name: test-cluster 5 | spec: 6 | clusterType: kubernetes 7 | masterList: 8 | - ip: 192.168.1.10 9 | - ip: 192.168.1.11 10 | nodeList: 11 | - ip: 192.168.1.12 12 | - ip: 192.168.1.12 13 | etcdList: 14 | - ip: 192.168.1.12 15 | - ip: 192.168.1.12 16 | privateSSHKey: '' 17 | serviceCIDR: '' 18 | status: {} 19 | -------------------------------------------------------------------------------- /scripts/test/create_cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | request_body=$((cat <= v1.9 7 | # docs: https://github.com/coredns/deployment/tree/master/kubernetes 8 | 9 | # TODO : download coredns 10 | download_coredns(){ 11 | git clone https://github.com/coredns/deployment 12 | } 13 | 14 | COERDNS_CONFIG="../yaml/coredns_${COREDNS_VER}/coredns.yaml" 15 | 16 | kubectl apply -f ${COERDNS_CONFIG} 17 | if [ $? -ne 0 ];then 18 | echo "deploy coredns failed !!!" && exit 1 19 | fi 20 | -------------------------------------------------------------------------------- /scripts/systemd/etcd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Etcd Server 3 | After=network.target 4 | After=network-online.target 5 | Wants=network-online.target 6 | 7 | [Service] 8 | Type=notify 9 | WorkingDirectory=/var/lib/etcd/ 10 | EnvironmentFile=-/etc/etcd/etcd.conf 11 | User=root 12 | # set GOMAXPROCS to number of processors 13 | ExecStart=/bin/bash -c "GOMAXPROCS=$(nproc) /usr/bin/etcd --name=\"${ETCD_NAME}\" --data-dir=\"${ETCD_DATA_DIR}\" --listen-client-urls=\"${ETCD_LISTEN_CLIENT_URLS}\"" 14 | Restart=on-failure 15 | RestartSec=5 16 | LimitNOFILE=65536 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | -------------------------------------------------------------------------------- /ansible/etcd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: etcd 17 | gather_facts: false 18 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 19 | environment: 20 | ETCD_HOSTS: ${ETCD_HOSTS} 21 | roles: 22 | - { role: kubernetes/preinstall, tags: preinstall } 23 | - { role: kubernetes/etcd, tags: etcd } 24 | -------------------------------------------------------------------------------- /ansible/inventory/production/group_vars/all.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # docker version 3 | DOCKER_VER: "docker-ce-18.06.1.ce" 4 | 5 | # k8s version 6 | KUBERNETES_VER: "kubernetes_v1.14.0" 7 | 8 | KUBERNETES_DOWNLOAD_URL: "https://dl.k8s.io/v1.14.0/kubernetes.tar.gz" 9 | 10 | # etcd version 11 | ETCD_VER: "etcd_v3.3.13" 12 | 13 | # calico version 14 | CALICO_VER: "v3.7" 15 | 16 | # coredns version 17 | COREDNS_VER: "v1.4.0" 18 | 19 | # etcd hosts, eg : "10.0.2.15,10.0.2.16" 20 | ETCD_HOSTS: "10.0.2.15" 21 | 22 | # master hosts, eg : "10.0.2.15,10.0.2.16" 23 | MASTER_HOSTS: "10.0.2.15" 24 | 25 | # host ip 26 | #LOCAL_IP: $(ip route get 1 | awk '{print $NF;exit}') 27 | 28 | disable_swap: true 29 | -------------------------------------------------------------------------------- /images/base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:19.04 2 | MAINTAINER gosoon 3 | 4 | # start a sshd service in image so that the container cannot exit 5 | # 6 | 7 | RUN apt-get update; apt-get upgrade -y \ 8 | && apt-get install -y openssh-server 9 | 10 | RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config 11 | 12 | RUN mkdir /var/run/sshd 13 | 14 | RUN mkdir -pv /kubernetes/bin \ 15 | && mkdir -pv /kubernetes/manifests \ 16 | && mkdir -pv /kubernetes/systemd 17 | 18 | Add ./bin /kubernetes/bin/ 19 | Add ./manifests /kubernetes/manifests/ 20 | Add ./systemd /kubernetes/systemd/ 21 | Add ./version /kubernetes/ 22 | Add ./kubeadm.conf /kubernetes/ 23 | 24 | EXPOSE 22 25 | ENTRYPOINT /usr/sbin/sshd -D 26 | -------------------------------------------------------------------------------- /scripts/certs/node/gen_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e ../../deploy/config.sh ] && . ../../deploy/config.sh || exit 4 | 5 | CERTS_DIR="/etc/kubernetes/ssl" 6 | [ -d output ] || mkdir output 7 | 8 | # kubelet 9 | cfssl gencert \ 10 | -ca=${CERTS_DIR}/ca.pem \ 11 | -ca-key=${CERTS_DIR}/ca-key.pem \ 12 | -config=ca-config.json \ 13 | -hostname=${NODE_HOSTNAME},${NODE_HOSTS} \ 14 | -profile=kubernetes \ 15 | kubelet-csr.json | cfssljson -bare output/kubelet 16 | 17 | # other component 18 | cfssl gencert \ 19 | -ca=${CERTS_DIR}/ca.pem \ 20 | -ca-key=${CERTS_DIR}/ca-key.pem \ 21 | -config=ca-config.json \ 22 | -profile=kubernetes \ 23 | kube-proxy-csr.json | cfssljson -bare output/kube-proxy 24 | -------------------------------------------------------------------------------- /ansible/remove-node.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: kube-node 17 | gather_facts: false 18 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 19 | environment: 20 | MASTER_HOSTS: ${MASTER_HOSTS} 21 | MASTER_VIP: ${MASTER_VIP} 22 | NODE_HOSTS: ${NODE_HOSTS} 23 | roles: 24 | - { role: kubernetes/remove-node, tags: remove-node } 25 | -------------------------------------------------------------------------------- /ansible/scaledown-node.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: kube-node 17 | gather_facts: false 18 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 19 | environment: 20 | MASTER_HOSTS: ${MASTER_HOSTS} 21 | MASTER_VIP: ${MASTER_VIP} 22 | NODE_HOSTS: ${NODE_HOSTS} 23 | roles: 24 | - { role: kubernetes/remove-node, tags: remove-node } 25 | -------------------------------------------------------------------------------- /ansible/scaleup-node.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: kube-node 17 | gather_facts: false 18 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 19 | environment: 20 | MASTER_HOSTS: ${MASTER_HOSTS} 21 | MASTER_VIP: ${MASTER_VIP} 22 | NODE_HOSTS: ${NODE_HOSTS} 23 | roles: 24 | - { role: kubernetes/remove-node, tags: remove-node } 25 | -------------------------------------------------------------------------------- /scripts/systemd/kubelet.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Kubernetes Kubelet Server 3 | Documentation=https://github.com/GoogleCloudPlatform/kubernetes 4 | After=docker.service 5 | Requires=docker.service 6 | 7 | [Service] 8 | WorkingDirectory=/var/lib/kubelet 9 | EnvironmentFile=-/etc/kubernetes/config 10 | EnvironmentFile=-/etc/kubernetes/kubelet 11 | ExecStart=/usr/bin/kubelet \ 12 | $KUBE_LOGTOSTDERR \ 13 | $KUBE_LOG_LEVEL \ 14 | $KUBELET_API_SERVER \ 15 | $KUBELET_ADDRESS \ 16 | $KUBELET_PORT \ 17 | $KUBELET_HOSTNAME \ 18 | $KUBE_ALLOW_PRIV \ 19 | $KUBELET_ARGS 20 | Restart=on-failure 21 | RestartSec=5 22 | KillMode=process 23 | 24 | [Install] 25 | WantedBy=multi-user.target 26 | -------------------------------------------------------------------------------- /scripts/config/master/controller-manager: -------------------------------------------------------------------------------- 1 | ### 2 | # The following values are used to configure the kubernetes controller-manager 3 | 4 | # defaults from config and apiserver should be adequate 5 | 6 | # Add your own! 7 | KUBE_CONTROLLER_MANAGER_ARGS=" --bind-address=127.0.0.1 \ 8 | --allocate-node-cidrs=true \ 9 | --cluster-cidr=10.244.0.0/16 \ 10 | --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \ 11 | --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \ 12 | --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \ 13 | --service-cluster-ip-range=10.250.0.0/24 \ 14 | --leader-elect=true \ 15 | --use-service-account-credentials=true \ 16 | --kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig" 17 | -------------------------------------------------------------------------------- /ansible/node.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: kube-node 17 | gather_facts: false 18 | environment: 19 | MASTER_HOSTS: ${MASTER_HOSTS} 20 | MASTER_VIP: ${MASTER_VIP} 21 | NODE_HOSTS: ${NODE_HOSTS} 22 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 23 | roles: 24 | - { role: kubernetes/preinstall, tags: preinstall } 25 | - { role: kubernetes/node, tags: node } 26 | -------------------------------------------------------------------------------- /scripts/systemd/kube-apiserver.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Kubernetes API Server 3 | Documentation=https://github.com/GoogleCloudPlatform/kubernetes 4 | After=network.target 5 | After=etcd.service 6 | 7 | [Service] 8 | EnvironmentFile=-/etc/kubernetes/config 9 | EnvironmentFile=-/etc/kubernetes/apiserver 10 | ExecStart=/usr/bin/kube-apiserver \ 11 | $KUBE_LOGTOSTDERR \ 12 | $KUBE_LOG_LEVEL \ 13 | $KUBE_ETCD_SERVERS \ 14 | $KUBE_API_ADDRESS \ 15 | $KUBE_API_PORT \ 16 | $KUBELET_PORT \ 17 | $KUBE_ALLOW_PRIV \ 18 | $KUBE_SERVICE_ADDRESSES \ 19 | $KUBE_ADMISSION_CONTROL \ 20 | $KUBE_API_ARGS 21 | Restart=on-failure 22 | RestartSec=5 23 | Type=notify 24 | LimitNOFILE=65536 25 | 26 | [Install] 27 | WantedBy=multi-user.target 28 | -------------------------------------------------------------------------------- /pkg/internal/cluster/create/validate.go: -------------------------------------------------------------------------------- 1 | package create 2 | 3 | import ( 4 | "errors" 5 | "strings" 6 | 7 | createtypes "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/create/types" 8 | ) 9 | 10 | func validate(cluster *createtypes.ClusterOptions) error { 11 | errs := []string{} 12 | if cluster.Config == nil { 13 | errs = append(errs, "invalid config") 14 | } 15 | 16 | if cluster.NodeImage == "" { 17 | errs = append(errs, "invalid node image") 18 | 19 | } 20 | 21 | if cluster.NodeAddress == "" { 22 | errs = append(errs, "invalid local ip") 23 | } 24 | 25 | if cluster.Role == "" { 26 | errs = append(errs, "invalid role") 27 | } 28 | 29 | if len(errs) > 0 { 30 | return errors.New(strings.Join(errs, "\n")) 31 | } 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /scripts/certs/etcd/gen_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e ../../deploy/config.sh ] && . ../../deploy/config.sh || exit 4 | [ -d output ] || mkdir output 5 | 6 | # etcd server cert/key 7 | cfssl gencert --initca=true etcd-root-ca-csr.json | cfssljson -bare output/ca 8 | 9 | # etcd server 10 | cfssl gencert \ 11 | -ca=output/ca.pem \ 12 | -ca-key=output/ca-key.pem \ 13 | -config=ca-config.json \ 14 | -hostname=127.0.0.1,${ETCD_HOSTS} \ 15 | -profile=server \ 16 | server.json | cfssljson -bare output/etcd-server 17 | 18 | # etcd peer 19 | cfssl gencert \ 20 | -ca=output/ca.pem \ 21 | -ca-key=output/ca-key.pem \ 22 | -config=ca-config.json \ 23 | -hostname=127.0.0.1,${ETCD_HOSTS} \ 24 | -profile=peer \ 25 | server.json | cfssljson -bare output/etcd-peer 26 | -------------------------------------------------------------------------------- /ansible/master.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: kube-master 17 | gather_facts: false 18 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 19 | environment: 20 | MASTER_HOSTS: ${MASTER_HOSTS} 21 | MASTER_VIP: ${MASTER_VIP} 22 | NODE_HOSTS: ${NODE_HOSTS} 23 | ETCD_HOSTS: ${ETCD_HOSTS} 24 | roles: 25 | - { role: kubernetes/preinstall, tags: preinstall } 26 | - { role: kubernetes/master, tags: master } 27 | -------------------------------------------------------------------------------- /ansible/terminating.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | gather_facts: false 4 | become: no 5 | tasks: 6 | - name: "Check ansible version >=2.7.6" 7 | assert: 8 | msg: "Ansible must be v2.7.6 or higher" 9 | that: 10 | - ansible_version.string is version("2.7.6", ">=") 11 | tags: 12 | - check 13 | vars: 14 | ansible_connection: local 15 | 16 | - hosts: kube-master 17 | gather_facts: false 18 | any_errors_fatal: "{{ any_errors_fatal | default(true) }}" 19 | environment: 20 | MASTER_HOSTS: ${MASTER_HOSTS} 21 | MASTER_VIP: ${MASTER_VIP} 22 | NODE_HOSTS: ${NODE_HOSTS} 23 | ETCD_HOSTS: ${ETCD_HOSTS} 24 | roles: 25 | - { role: kubernetes/preinstall, tags: preinstall } 26 | - { role: kubernetes/master, tags: master } 27 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated clientset. 20 | package versioned 21 | -------------------------------------------------------------------------------- /scripts/certs/etcd/ca-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "8760h" 5 | }, 6 | "profiles": { 7 | "server": { 8 | "expiry": "8760h", 9 | "usages": [ 10 | "signing", 11 | "key encipherment", 12 | "server auth", 13 | "client auth" 14 | ] 15 | }, 16 | "client": { 17 | "expiry": "8760h", 18 | "usages": [ 19 | "signing", 20 | "key encipherment", 21 | "client auth" 22 | ] 23 | }, 24 | "peer": { 25 | "expiry": "8760h", 26 | "usages": [ 27 | "signing", 28 | "key encipherment", 29 | "server auth", 30 | "client auth" 31 | ] 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated fake clientset. 20 | package fake 21 | -------------------------------------------------------------------------------- /scripts/config/master/config: -------------------------------------------------------------------------------- 1 | ### 2 | # kubernetes system config 3 | # 4 | # The following values are used to configure various aspects of all 5 | # kubernetes services, including 6 | # 7 | # kube-apiserver.service 8 | # kube-controller-manager.service 9 | # kube-scheduler.service 10 | # kubelet.service 11 | # kube-proxy.service 12 | # logging to stderr means we get it in the systemd journal 13 | KUBE_LOGTOSTDERR="--logtostderr=false" 14 | 15 | # journal message level, 0 is debug 16 | KUBE_LOG_LEVEL="--v=3" 17 | 18 | # Should this cluster be allowed to run privileged docker containers 19 | KUBE_ALLOW_PRIV="--allow-privileged=true" 20 | 21 | # How the controller-manager, scheduler, and proxy find the apiserver 22 | KUBE_MASTER="--master=https://:6443 --log-dir=/var/log/kubernetes" 23 | -------------------------------------------------------------------------------- /scripts/config/node/config: -------------------------------------------------------------------------------- 1 | ### 2 | # kubernetes system config 3 | # 4 | # The following values are used to configure various aspects of all 5 | # kubernetes services, including 6 | # 7 | # kube-apiserver.service 8 | # kube-controller-manager.service 9 | # kube-scheduler.service 10 | # kubelet.service 11 | # kube-proxy.service 12 | # logging to stderr means we get it in the systemd journal 13 | KUBE_LOGTOSTDERR="--logtostderr=false" 14 | 15 | # journal message level, 0 is debug 16 | KUBE_LOG_LEVEL="--v=3" 17 | 18 | # Should this cluster be allowed to run privileged docker containers 19 | #KUBE_ALLOW_PRIV="--allow-privileged=true" 20 | 21 | # How the controller-manager, scheduler, and proxy find the apiserver 22 | KUBE_MASTER="--master=https://:6443 --log-dir=/var/log/kubernetes" 23 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/ecs/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated typed clients. 20 | package v1 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/ecs/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // Package fake has the automatically generated clients. 20 | package fake 21 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/ecs/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | type KubernetesClusterExpansion interface{} 22 | -------------------------------------------------------------------------------- /test/delete_ecs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | region="default" 4 | name="test-cluster" 5 | request_body=$(cat<mock_service/service.go 18 | mockgen github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned Interface >mock_versioned/service.go 19 | mockgen k8s.io/client-go/kubernetes Interface >mock_kubernetes/service.go 20 | -------------------------------------------------------------------------------- /pkg/installer/cluster/nodes/command.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nodes 18 | 19 | import ( 20 | "github.com/gosoon/kubernetes-operator/pkg/exec" 21 | ) 22 | 23 | // Command returns a new exec.Cmd that will run on the node 24 | func Command(command string, args ...string) exec.Cmd { 25 | return exec.Command(command, args...) 26 | } 27 | -------------------------------------------------------------------------------- /ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | pipelining=True 3 | ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFile=/dev/null 4 | #control_path = ~/.ssh/ansible-%%r@%%h:%%p 5 | [defaults] 6 | strategy_plugins = plugins/mitogen/ansible_mitogen/plugins/strategy 7 | # https://github.com/ansible/ansible/issues/56930 (to ignore group names with - and .) 8 | force_valid_group_names = ignore 9 | 10 | host_key_checking=False 11 | gathering = smart 12 | fact_caching = jsonfile 13 | fact_caching_connection = /tmp 14 | stdout_callback = skippy 15 | library = ./library 16 | callback_whitelist = profile_tasks 17 | roles_path = roles:$VIRTUAL_ENV/usr/local/share/kubespray/roles:$VIRTUAL_ENV/usr/local/share/ansible/roles:/usr/share/kubespray/roles 18 | deprecation_warnings=False 19 | inventory_ignore_extensions = ~, .orig, .bak, .ini, .cfg, .retry, .pyc, .pyo, .creds 20 | [inventory] 21 | ignore_patterns = artifacts, credentials 22 | enable_plugins = yaml 23 | -------------------------------------------------------------------------------- /deploy/kube-operator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: kubernetes-operator 5 | namespace: ecs-system 6 | spec: 7 | replicas: 3 8 | selector: 9 | matchLabels: 10 | name: kubernetes-operator 11 | template: 12 | metadata: 13 | labels: 14 | name: kubernetes-operator 15 | spec: 16 | serviceAccountName: kubernetes-operator 17 | containers: 18 | - name: kubernetes-operator 19 | # Replace this with the built image name 20 | image: REPLACE_IMAGE 21 | imagePullPolicy: Always 22 | env: 23 | - name: WATCH_NAMESPACE 24 | valueFrom: 25 | fieldRef: 26 | fieldPath: metadata.namespace 27 | - name: POD_NAME 28 | valueFrom: 29 | fieldRef: 30 | fieldPath: metadata.name 31 | - name: OPERATOR_NAME 32 | value: "kubernetes-operator" 33 | -------------------------------------------------------------------------------- /pkg/internal/util/env/term.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package env 18 | 19 | import ( 20 | "io" 21 | "os" 22 | 23 | "golang.org/x/crypto/ssh/terminal" 24 | ) 25 | 26 | // IsTerminal returns true if the writer w is a terminal 27 | func IsTerminal(w io.Writer) bool { 28 | if v, ok := (w).(*os.File); ok { 29 | return terminal.IsTerminal(int(v.Fd())) 30 | } 31 | return false 32 | } 33 | -------------------------------------------------------------------------------- /pkg/precheck/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package precheck 18 | 19 | import ( 20 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 21 | "github.com/gosoon/kubernetes-operator/pkg/types" 22 | ) 23 | 24 | // Interface xxx 25 | type Interface interface { 26 | HostEnv(cluster *ecsv1.KubernetesCluster, results []chan types.PrecheckResult, finished chan bool) 27 | } 28 | -------------------------------------------------------------------------------- /scripts/deploy/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # this section is glabel vars,do not edit 4 | # deploy home 5 | DEPLOY_HOME_DIR="/home/kubernetes-operator" 6 | 7 | # export certs bin 8 | CERTS_BIN_DIR="scripts/bin/certs" 9 | export PATH=$PATH:${DEPLOY_HOME_DIR}/${CERTS_BIN_DIR} 10 | 11 | # ---------------- 12 | # this section is define by users 13 | # docker version 14 | DOCKER_VER="docker-ce-18.06.1.ce" 15 | 16 | # k8s version 17 | KUBERNETES_VER="kubernetes_v1.14.0" 18 | KUBERNETES_DOWNLOAD_URL="https://dl.k8s.io/v1.14.0/kubernetes.tar.gz" 19 | 20 | # etcd version 21 | ETCD_VER="etcd_v3.3.13" 22 | 23 | # calico version 24 | CALICO_VER="v3.7" 25 | 26 | # coredns version 27 | COREDNS_VER="v1.4.0" 28 | 29 | LOCAL_IP=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1') 30 | 31 | # if in docker and use env 32 | ENV_FILE="${DEPLOY_HOME_DIR}/scripts/deploy/hosts_env" 33 | if ! grep docker /proc/1/cgroup -qa; then 34 | [ -f ${ENV_FILE} ] && source ${ENV_FILE} || exit 1 35 | fi 36 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gosoon/kubernetes-operator 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/cloudflare/cfssl v0.0.0-20190911221928-1a911ca1b1d6 7 | github.com/deckarep/golang-set v1.7.1 8 | github.com/gogo/protobuf v1.2.1 9 | github.com/golang/mock v1.1.1 10 | github.com/golang/protobuf v1.3.1 11 | github.com/gorilla/mux v1.7.3 12 | github.com/gosoon/glog v0.0.0-20180521124921-a5fbfb162a81 13 | github.com/grpc-ecosystem/grpc-gateway v1.9.0 14 | github.com/kr/fs v0.1.0 // indirect 15 | github.com/mitchellh/go-homedir v1.1.0 16 | github.com/pkg/errors v0.8.1 17 | github.com/pkg/sftp v1.10.0 18 | github.com/sirupsen/logrus v1.2.0 19 | github.com/spf13/cobra v0.0.5 20 | github.com/spf13/viper v1.4.0 21 | github.com/stretchr/testify v1.3.0 22 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 23 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 24 | google.golang.org/grpc v1.21.0 25 | k8s.io/api v0.0.0-20190718062839-c8a0b81cb10e 26 | k8s.io/apimachinery v0.0.0-20190717022731-0bb8574e0887 27 | sigs.k8s.io/yaml v1.1.0 28 | ) 29 | -------------------------------------------------------------------------------- /cmd/installer/grpc/agent/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | "math/rand" 22 | "os" 23 | "time" 24 | 25 | "github.com/gosoon/kubernetes-operator/cmd/installer/grpc/agent/app" 26 | ) 27 | 28 | func main() { 29 | rand.Seed(time.Now().UnixNano()) 30 | 31 | command := app.NewServerCommand() 32 | if err := command.Execute(); err != nil { 33 | fmt.Fprintf(os.Stderr, "%v\n", err) 34 | os.Exit(1) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /pkg/utils/pointer/pointer.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package pointer 18 | 19 | // reference: https://github.com/kubernetes/utils 20 | 21 | // Int32Ptr returns a pointer to an int64 22 | func Int32Ptr(i int32) *int32 { 23 | return &i 24 | } 25 | 26 | // Int64Ptr returns a pointer to an int64 27 | func Int64Ptr(i int64) *int64 { 28 | return &i 29 | } 30 | 31 | // BoolPtr returns a pointer to an bool 32 | func BoolPtr(b bool) *bool { 33 | return &b 34 | } 35 | -------------------------------------------------------------------------------- /cmd/installer/grpc/server/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | "math/rand" 22 | "os" 23 | "time" 24 | 25 | "github.com/gosoon/kubernetes-operator/cmd/installer/grpc/server/app" 26 | ) 27 | 28 | func main() { 29 | rand.Seed(time.Now().UnixNano()) 30 | 31 | command := app.NewServerCommand() 32 | if err := command.Execute(); err != nil { 33 | fmt.Fprintf(os.Stderr, "%v\n", err) 34 | os.Exit(1) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /scripts/deploy/base_env_01.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # disable swap 4 | swapoff -a 5 | 6 | # Set SELinux in permissive mode (effectively disabling it) 7 | setenforce 0 8 | sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config 9 | 10 | # disable firewall 11 | systemctl disable firewalld.service && systemctl stop firewalld.service 12 | 13 | # use aliyun kubernetes yum source 14 | cat < /etc/yum.repos.d/kubernetes.repo 15 | [kubernetes] 16 | name=Kubernetes 17 | baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 18 | enabled=1 19 | gpgcheck=1 20 | repo_gpgcheck=1 21 | gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg 22 | EOF 23 | 24 | cat < /etc/sysctl.d/k8s.conf 25 | net.bridge.bridge-nf-call-ip6tables = 1 26 | net.bridge.bridge-nf-call-iptables = 1 27 | EOF 28 | sysctl --system &> /dev/null 29 | 30 | # install scp 31 | if [ ! -f /usr/bin/scp ];then 32 | yum install openssh-clients -y 33 | [ $? -eq 0 ] || { echo "install scp failed"; exit 1; } 34 | fi 35 | -------------------------------------------------------------------------------- /pkg/client/listers/ecs/v1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by lister-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | // KubernetesClusterListerExpansion allows custom methods to be added to 22 | // KubernetesClusterLister. 23 | type KubernetesClusterListerExpansion interface{} 24 | 25 | // KubernetesClusterNamespaceListerExpansion allows custom methods to be added to 26 | // KubernetesClusterNamespaceLister. 27 | type KubernetesClusterNamespaceListerExpansion interface{} 28 | -------------------------------------------------------------------------------- /pkg/installer/grpc/server/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package server 18 | 19 | import installerv1 "github.com/gosoon/kubernetes-operator/pkg/apis/installer/v1" 20 | 21 | // injectClusterConfig is set some config by server,eg:image registry and node role 22 | // current only inject images registry 23 | func (inst *installer) injectClusterConfig(cluster *installerv1.KubernetesClusterRequest) *installerv1.KubernetesClusterRequest { 24 | cluster.Spec.Cluster.ImagesRegistry = inst.opt.ImagesRegistry 25 | return cluster 26 | } 27 | -------------------------------------------------------------------------------- /pkg/server/service/valid.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 21 | "github.com/gosoon/kubernetes-operator/pkg/enum" 22 | ) 23 | 24 | // valid operate 25 | func validPhase(kubernetesCluster *ecsv1.KubernetesCluster) bool { 26 | phase := kubernetesCluster.Status.Phase 27 | if phase == enum.New || phase == enum.Creating || phase == enum.Scaling || 28 | phase == enum.Terminating { 29 | return false 30 | } 31 | return true 32 | } 33 | -------------------------------------------------------------------------------- /pkg/types/precheck.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package types 18 | 19 | import "time" 20 | 21 | // SSHInfo xxx 22 | type SSHInfo struct { 23 | IP string 24 | Port int 25 | Username string 26 | Password string 27 | CmdFile string 28 | Cmds string 29 | CmdList []string 30 | Key string 31 | CipherList []string 32 | Timeout time.Duration 33 | Result PrecheckResult 34 | } 35 | 36 | // PrecheckResult xxx 37 | type PrecheckResult struct { 38 | Host string 39 | CmdList []string 40 | Success bool 41 | Result string 42 | } 43 | -------------------------------------------------------------------------------- /pkg/internal/cluster/kubeadm/const.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package kubeadm 18 | 19 | // APIServerPort is the expected default APIServerPort on the control plane node(s) 20 | // https://kubernetes.io/docs/reference/access-authn-authz/controlling-access/#api-server-ports-and-ips 21 | const APIServerPort = 6443 22 | 23 | // Token defines a dummy, well known token for automating TLS bootstrap process 24 | const Token = "abcdef.0123456789abcdef" 25 | 26 | // ObjectName is the name every generated object will have 27 | // I.E. `metadata:\nname: config` 28 | const ObjectName = "config" 29 | -------------------------------------------------------------------------------- /scripts/config/etcd/etcd.conf: -------------------------------------------------------------------------------- 1 | ETCD_NAME="node1" 2 | ETCD_DATA_DIR="/home/etcd_1/data" 3 | ETCD_LISTEN_PEER_URLS="https://0.0.0.0:2380" 4 | ETCD_LISTEN_CLIENT_URLS="https://0.0.0.0:2379,https://0.0.0.0:4001" 5 | ETCD_INITIAL_ADVERTISE_PEER_URLS="https://xxx:2380" 6 | ETCD_ADVERTISE_CLIENT_URLS="https://xxx:2379" 7 | ETCD_INITIAL_CLUSTER_TOKEN="local" 8 | ETCD_INITIAL_CLUSTER="node0=https://xxx:2380,node1=https://xxx:2380,node2=https://xxx:2380,node3=https://xxx:2380,node4=https://xxx:2380" 9 | ETCD_INITIAL_CLUSTER_STATE="new" 10 | #ETCD_INITIAL_CLUSTER_STATE="existing" 11 | 12 | ETCD_HEARTBEAT_INTERVAL="300" 13 | ETCD_ELECTION_TIMEOUT="1500" 14 | ETCD_MAX_SNAPSHOTS="10" 15 | ETCD_MAX_WALS="10" 16 | ETCD_QUOTA_BACKEND_BYTES="8589934592" 17 | 18 | ETCD_CERT_FILE="/etc/etcd/ssl/etcd-server.pem" 19 | ETCD_KEY_FILE="/etc/etcd/ssl/etcd-server-key.pem" 20 | ETCD_PEER_CERT_FILE="/etc/etcd/ssl/etcd-peer.pem" 21 | ETCD_PEER_KEY_FILE="/etc/etcd/ssl/etcd-peer-key.pem" 22 | ETCD_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.pem" 23 | ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/ssl/ca.pem" 24 | ETCD_CLIENT_CERT_AUTH="true" 25 | ETCD_PEER_CLIENT_CERT_AUTH="true" 26 | 27 | ETCD_DEBUG="false" 28 | ETCD_LOG_PACKAGE_LEVELS="etcdserver=WARNING,security=DEBUG" 29 | -------------------------------------------------------------------------------- /pkg/server/controller/controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | clientset "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned" 21 | "github.com/gosoon/kubernetes-operator/pkg/server/service" 22 | 23 | "github.com/gorilla/mux" 24 | "k8s.io/client-go/kubernetes" 25 | ) 26 | 27 | type Options struct { 28 | KubernetesClusterClientset clientset.Interface 29 | KubeClientset kubernetes.Interface 30 | Service service.Interface 31 | } 32 | 33 | type Controller interface { 34 | Register(router *mux.Router) 35 | } 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | # Force-enable Go modules. Also force go to use the code in vendor/ 4 | # These will both be unnecessary when Go 1.13 lands. 5 | env: 6 | - GO111MODULE=on 7 | - GOFLAGS='-mod vendor' 8 | 9 | # You don't need to test on very old versions of the Go compiler. It's the user's 10 | # responsibility to keep their compiler up to date. 11 | go: 12 | - 1.12.x 13 | - master 14 | 15 | # Only clone the most recent commit. 16 | git: 17 | depth: 1 18 | 19 | # Don't email me the results of the test runs. 20 | notifications: 21 | email: false 22 | 23 | # Anything in before_script that returns a nonzero exit code will flunk the 24 | # build and immediately stop. It's sorta like having set -e enabled in bash. 25 | # Make sure golangci-lint is vendored. 26 | before_script: 27 | - go install github.com/golangci/golangci-lint/cmd/golangci-lint 28 | 29 | 30 | # script always runs to completion (set +e). If we have linter issues AND a 31 | # failing test, we want to see both. Configure golangci-lint with a 32 | # .golangci.yml file at the top level of your repo. 33 | script: 34 | - golangci-lint run # run a bunch of code checkers/linters in parallel 35 | - go test -v -race ./... # Run all the tests with the race detector enabled 36 | -------------------------------------------------------------------------------- /pkg/apis/ecs/v1/register.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "github.com/gosoon/kubernetes-operator/pkg/apis/ecs" 5 | 6 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 7 | "k8s.io/apimachinery/pkg/runtime" 8 | "k8s.io/apimachinery/pkg/runtime/schema" 9 | ) 10 | 11 | // SchemeGroupVersion is group version used to register these objects 12 | var SchemeGroupVersion = schema.GroupVersion{Group: ecs.GroupName, Version: "v1"} 13 | 14 | // Kind takes an unqualified kind and returns back a Group qualified GroupKind 15 | func Kind(kind string) schema.GroupKind { 16 | return SchemeGroupVersion.WithKind(kind).GroupKind() 17 | } 18 | 19 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 20 | func Resource(resource string) schema.GroupResource { 21 | return SchemeGroupVersion.WithResource(resource).GroupResource() 22 | } 23 | 24 | var ( 25 | SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) 26 | AddToScheme = SchemeBuilder.AddToScheme 27 | ) 28 | 29 | // Adds the list of known types to Scheme. 30 | func addKnownTypes(scheme *runtime.Scheme) error { 31 | scheme.AddKnownTypes(SchemeGroupVersion, 32 | &KubernetesCluster{}, 33 | &KubernetesClusterList{}, 34 | ) 35 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /scripts/systemd/docker.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Docker Application Container Engine 3 | Documentation=https://docs.docker.com 4 | After=network-online.target firewalld.service 5 | Wants=network-online.target 6 | 7 | [Service] 8 | Type=notify 9 | # the default is not to use systemd for cgroups because the delegate issues still 10 | # exists and systemd currently does not support the cgroup feature set required 11 | # for containers run by docker 12 | ExecStart=/usr/bin/dockerd 13 | ExecReload=/bin/kill -s HUP $MAINPID 14 | # Having non-zero Limit*s causes performance problems due to accounting overhead 15 | # in the kernel. We recommend using cgroups to do container-local accounting. 16 | LimitNOFILE=infinity 17 | LimitNPROC=infinity 18 | LimitCORE=infinity 19 | # Uncomment TasksMax if your systemd version supports it. 20 | # Only systemd 226 and above support this version. 21 | #TasksMax=infinity 22 | TimeoutStartSec=0 23 | # set delegate yes so that systemd does not reset the cgroups of docker containers 24 | Delegate=yes 25 | # kill only the docker process, not all processes in the cgroup 26 | KillMode=process 27 | # restart the docker process if it exits prematurely 28 | Restart=on-failure 29 | StartLimitBurst=3 30 | StartLimitInterval=60s 31 | 32 | [Install] 33 | WantedBy=multi-user.target 34 | -------------------------------------------------------------------------------- /pkg/installer/ssh/ssh.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ssh 18 | 19 | import ( 20 | clientset "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned" 21 | 22 | "k8s.io/client-go/kubernetes" 23 | "k8s.io/client-go/tools/record" 24 | ) 25 | 26 | // Options is ssh installer must flags. 27 | type Options struct { 28 | Kubeclientset kubernetes.Interface 29 | KubernetesClusterClientset clientset.Interface 30 | Recorder record.EventRecorder 31 | } 32 | 33 | type installer struct { 34 | opt *Options 35 | } 36 | 37 | // NewSSHInstaller is new a ssh installer object. 38 | func NewSSHInstaller(o *Options) *installer { 39 | return &installer{opt: o} 40 | } 41 | -------------------------------------------------------------------------------- /pkg/installer/ssh/batchjob_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ssh 18 | 19 | import ( 20 | "testing" 21 | 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 23 | "github.com/gosoon/kubernetes-operator/pkg/enum" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | ) 26 | 27 | func TestNewCreateKubernetesClusterJob(t *testing.T) { 28 | testCases := []*ecsv1.KubernetesCluster{ 29 | &ecsv1.KubernetesCluster{ 30 | ObjectMeta: metav1.ObjectMeta{ 31 | Name: "test-1", 32 | }, 33 | Status: ecsv1.KubernetesClusterStatus{ 34 | Phase: enum.Running, 35 | }, 36 | }, 37 | } 38 | for _, test := range testCases { 39 | _ = newCreateKubernetesClusterJob(test) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /scripts/certs/master/gen_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e ../../deploy/config.sh ] && . ../../deploy/config.sh || exit 4 | [ -d output ] || mkdir output 5 | 6 | cfssl gencert -initca ca-csr.json | cfssljson -bare output/ca 7 | 8 | # apiserver 9 | cfssl gencert \ 10 | -ca=output/ca.pem \ 11 | -ca-key=output/ca-key.pem \ 12 | -config=ca-config.json \ 13 | -hostname=10.250.0.1,${MASTER_HOSTS},${MASTER_VIP},127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc \ 14 | -profile=kubernetes \ 15 | kube-apiserver-csr.json | cfssljson -bare output/kube-apiserver 16 | 17 | # kubelet 18 | for node in `echo ${NODE_HOSTS} | tr ',' ' '`;do 19 | sed -i -e "s##${node}#g" kubelet-csr.json 20 | cfssl gencert \ 21 | -ca=output/ca.pem \ 22 | -ca-key=output/ca-key.pem \ 23 | -config=ca-config.json \ 24 | -hostname=${NODE_HOSTS} \ 25 | -profile=kubernetes \ 26 | kubelet-csr.json | cfssljson -bare output/kubelet 27 | done 28 | 29 | # other component 30 | for component in kube-controller-manager kube-scheduler kube-proxy apiserver-kubelet-client admin service-account;do 31 | cfssl gencert \ 32 | -ca=output/ca.pem \ 33 | -ca-key=output/ca-key.pem \ 34 | -config=ca-config.json \ 35 | -profile=kubernetes \ 36 | ${component}-csr.json | cfssljson -bare output/${component} 37 | done 38 | -------------------------------------------------------------------------------- /pkg/sshserver/sftp.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package sshserver 18 | 19 | import ( 20 | "os" 21 | 22 | "github.com/gosoon/glog" 23 | ) 24 | 25 | func (s *sshServer) CopyFile(localFilePath string, remoteFilePath string) error { 26 | srcFile, err := os.Open(localFilePath) 27 | if err != nil { 28 | glog.Errorf("scp to %v err: %v", s.IP, err) 29 | return err 30 | } 31 | defer srcFile.Close() 32 | 33 | dstFile, err := s.SftpClient.Create(remoteFilePath) 34 | if err != nil { 35 | glog.Errorf("scp to %v err: %v", s.IP, err) 36 | return err 37 | } 38 | defer dstFile.Close() 39 | 40 | buf := make([]byte, 1024) 41 | for { 42 | n, _ := srcFile.Read(buf) 43 | if n == 0 { 44 | break 45 | } 46 | dstFile.Write(buf[0:n]) 47 | } 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /pkg/installer/cluster/constants/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package constants 18 | 19 | // DefaultClusterName is the default cluster Context name 20 | const DefaultClusterName = "default" 21 | 22 | const ( 23 | // ExternalLoadBalancerNodeRoleValue identifies a node that hosts an 24 | // external load balancer for the API server in HA configurations. 25 | ExternalLoadBalancerNodeRoleValue string = "external-load-balancer" 26 | 27 | // ExternalEtcdNodeRoleValue identifies a node that hosts an external-etcd 28 | // instance. 29 | // 30 | // WARNING: this node type is not yet implemented! 31 | // 32 | ExternalEtcdNodeRoleValue string = "external-etcd" 33 | 34 | // InstallPath is write kubeadm config default path 35 | InstallPath string = "/tmp/install/" 36 | ) 37 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/ecs/v1/fake/fake_ecs_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | v1 "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned/typed/ecs/v1" 23 | rest "k8s.io/client-go/rest" 24 | testing "k8s.io/client-go/testing" 25 | ) 26 | 27 | type FakeEcsV1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeEcsV1) KubernetesClusters(namespace string) v1.KubernetesClusterInterface { 32 | return &FakeKubernetesClusters{c, namespace} 33 | } 34 | 35 | // RESTClient returns a RESTClient that is used to communicate 36 | // with API server by this client implementation. 37 | func (c *FakeEcsV1) RESTClient() rest.Interface { 38 | var ret *rest.RESTClient 39 | return ret 40 | } 41 | -------------------------------------------------------------------------------- /pkg/internal/cluster/create/types/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package types 18 | 19 | import ( 20 | "time" 21 | 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 23 | "github.com/gosoon/kubernetes-operator/pkg/internal/apis/config" 24 | ) 25 | 26 | // ClusterOptions holds cluster creation options 27 | // NOTE: this is only exported for usage by the parent package and the options 28 | // package 29 | // See ClusterOption instead 30 | type ClusterOptions struct { 31 | Name string 32 | Config *config.Cluster 33 | NodeImage string 34 | WaitForReady time.Duration 35 | SetupKubernetes bool 36 | NodeAddress string 37 | Role ecsv1.NodeRole 38 | ExternalLoadBalancer string 39 | KubeConfigPath string 40 | } 41 | -------------------------------------------------------------------------------- /pkg/types/ansible.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package types 18 | 19 | // HostsYamlFormat xxx 20 | type HostsYamlFormat struct { 21 | All AllHosts `json:"all"` 22 | } 23 | 24 | // AllHosts xxx 25 | type AllHosts struct { 26 | Hosts map[string]*Host `json:"hosts"` 27 | Children Children `json:"children"` 28 | } 29 | 30 | // Children xxx 31 | type Children struct { 32 | KubeMaster map[string]map[string]*Host `json:"kube-master"` 33 | KubeNode map[string]map[string]*Host `json:"kube-node"` 34 | Etcd map[string]map[string]*Host `json:"etcd"` 35 | Calico map[string]map[string]*Host `json:"calico-rr"` 36 | } 37 | 38 | // Host xxx 39 | type Host struct { 40 | AnsibleHost string `json:"ansible_host,omitempty"` 41 | IP string `json:"ip,omitempty"` 42 | AccessIP string `json:"access_ip,omitempty"` 43 | } 44 | -------------------------------------------------------------------------------- /pkg/installer/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package installer 18 | 19 | import ( 20 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 21 | ) 22 | 23 | // Interface is a installer interface define all installer implementation operation 24 | // you can define your self installer 25 | type Interface interface { 26 | // ClusterNew is creating a new cluster 27 | ClusterNew(cluster *ecsv1.KubernetesCluster) error 28 | 29 | // ClusterScaleUp is scale up a cluster node 30 | ClusterScaleUp(cluster *ecsv1.KubernetesCluster, scaleUpNodeList []ecsv1.Node) error 31 | 32 | // ClusterScaleDown is scale down a cluster node 33 | ClusterScaleDown(cluster *ecsv1.KubernetesCluster, scaleDownNodeList []ecsv1.Node) error 34 | 35 | // ClusterTerminating is delete a cluster 36 | ClusterTerminating(cluster *ecsv1.KubernetesCluster) error 37 | } 38 | -------------------------------------------------------------------------------- /deploy/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: kubernetes-operator 5 | namespace: ecs-system 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - pods 11 | - services 12 | - endpoints 13 | - persistentvolumeclaims 14 | - events 15 | - configmaps 16 | - secrets 17 | verbs: 18 | - '*' 19 | - apiGroups: 20 | - apps 21 | resources: 22 | - deployments 23 | - daemonsets 24 | - replicasets 25 | - statefulsets 26 | verbs: 27 | - '*' 28 | - apiGroups: 29 | - batch 30 | resources: 31 | - cronjobs 32 | - jobs 33 | verbs: 34 | - '*' 35 | - apiGroups: 36 | - monitoring.coreos.com 37 | resources: 38 | - servicemonitors 39 | verbs: 40 | - get 41 | - create 42 | - apiGroups: 43 | - apps 44 | resourceNames: 45 | - kubernetes-operator 46 | resources: 47 | - deployments/finalizers 48 | verbs: 49 | - update 50 | - apiGroups: 51 | - ecs.yun.com 52 | resources: 53 | - '*' 54 | verbs: 55 | - '*' 56 | --- 57 | kind: ClusterRoleBinding 58 | apiVersion: rbac.authorization.k8s.io/v1 59 | metadata: 60 | name: kubernetes-operator 61 | subjects: 62 | - kind: ServiceAccount 63 | name: kubernetes-operator 64 | namespace: ecs-system 65 | roleRef: 66 | kind: ClusterRole 67 | name: kubernetes-operator 68 | apiGroup: rbac.authorization.k8s.io 69 | --- 70 | apiVersion: v1 71 | kind: ServiceAccount 72 | metadata: 73 | name: kubernetes-operator 74 | namespace: ecs-system 75 | -------------------------------------------------------------------------------- /pkg/container/docker/cp.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package docker 18 | 19 | import ( 20 | "github.com/gosoon/kubernetes-operator/pkg/exec" 21 | ) 22 | 23 | // CopyTo copies the file at hostPath to the container at destPath 24 | func CopyTo(hostPath, containerNameOrID, destPath string) error { 25 | cmd := exec.Command( 26 | "docker", "cp", 27 | hostPath, // from the source file 28 | containerNameOrID+":"+destPath, // to the node, at dest 29 | ) 30 | return cmd.Run() 31 | } 32 | 33 | // CopyFrom copies the file or dir in the container at srcPath to the host at hostPath 34 | func CopyFrom(containerNameOrID, srcPath, hostPath string) error { 35 | cmd := exec.Command( 36 | "docker", "cp", 37 | containerNameOrID+":"+srcPath, // from the node, at src 38 | hostPath, // to the host 39 | ) 40 | return cmd.Run() 41 | } 42 | -------------------------------------------------------------------------------- /pkg/installer/cluster/nodes/role.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nodes 18 | 19 | import ( 20 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 21 | "github.com/gosoon/kubernetes-operator/pkg/internal/apis/config" 22 | 23 | "github.com/pkg/errors" 24 | ) 25 | 26 | // BootstrapControlPlaneNode returns a handle to the bootstrap control plane node 27 | func BootstrapControlPlaneNode(allNodes []config.Node) (*config.Node, error) { 28 | controlPlaneNode := &config.Node{} 29 | for _, node := range allNodes { 30 | if node.Role == ecsv1.ControlPlaneRole { 31 | controlPlaneNode.IP = node.IP 32 | controlPlaneNode.Role = node.Role 33 | } 34 | } 35 | 36 | if controlPlaneNode == nil { 37 | return nil, errors.Errorf( 38 | "expected at least one %s node", 39 | ecsv1.ControlPlaneRole, 40 | ) 41 | } 42 | return controlPlaneNode, nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/utils/signals/signals.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package signals 18 | 19 | import ( 20 | "os" 21 | "os/signal" 22 | "syscall" 23 | ) 24 | 25 | var onlyOneSignalHandler = make(chan struct{}) 26 | var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} 27 | 28 | // SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned 29 | // which is closed on one of these signals. If a second signal is caught, the program 30 | // is terminated with exit code 1. 31 | func SetupSignalHandler() (stopCh <-chan struct{}) { 32 | close(onlyOneSignalHandler) // panics when called twice 33 | 34 | stop := make(chan struct{}) 35 | c := make(chan os.Signal, 2) 36 | signal.Notify(c, shutdownSignals...) 37 | go func() { 38 | <-c 39 | close(stop) 40 | <-c 41 | os.Exit(1) // second signal. Exit directly. 42 | }() 43 | 44 | return stop 45 | } 46 | -------------------------------------------------------------------------------- /pkg/internal/cluster/create/images.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package create 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | 23 | "github.com/gosoon/kubernetes-operator/pkg/container/docker" 24 | "github.com/gosoon/kubernetes-operator/pkg/internal/util/cli" 25 | ) 26 | 27 | // ensureNodeImages ensures that the node images used by the create 28 | // configuration are present 29 | func ensureNodeImages(status *cli.Status, image string) { 30 | // prints user friendly message 31 | if strings.Contains(image, "@sha256:") { 32 | image = strings.Split(image, "@sha256:")[0] 33 | } 34 | status.Start(fmt.Sprintf("Ensuring node image (%s) ", image)) 35 | 36 | fmt.Println("pull image ...") 37 | // attempt to explicitly pull the image if it doesn't exist locally 38 | // we don't care if this errors, we'll still try to run which also pulls 39 | _, _ = docker.PullIfNotPresent(image, 3) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/internal/cluster/create/actions/action.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package actions 18 | 19 | import ( 20 | createtypes "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/create/types" 21 | "github.com/gosoon/kubernetes-operator/pkg/internal/util/cli" 22 | "google.golang.org/grpc" 23 | ) 24 | 25 | type Action interface { 26 | Execute(ctx *ActionContext) error 27 | } 28 | 29 | // ActionContext is data supplied to all actions 30 | type ActionContext struct { 31 | Status *cli.Status 32 | Cluster *createtypes.ClusterOptions 33 | Server *grpc.Server 34 | Port string 35 | } 36 | 37 | func NewActionContext( 38 | cluster *createtypes.ClusterOptions, 39 | server *grpc.Server, 40 | port string, 41 | status *cli.Status, 42 | ) *ActionContext { 43 | return &ActionContext{ 44 | Status: status, 45 | Cluster: cluster, 46 | Server: server, 47 | Port: port, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GOFILES := $(shell find . -name '*.go' | grep -v -E '(./vendor)') 2 | BIN := $(shell basename $(CURDIR)) 3 | # PLATFORM := $(shell go env GOOS) 4 | PLATFORM := linux 5 | AnsibleinitPath := cmd/installer/ssh/ansibleinit.go 6 | OperatorPath := cmd/kube-operator/app.go 7 | 8 | # ifneq (PLATFORM, "windows") 9 | # PLATFORM = linux 10 | # endif 11 | 12 | .DEFAULT_GOAL := default 13 | 14 | default: $(PLATFORM) 15 | 16 | all: linux darwin windows 17 | 18 | linux: output/$(BIN) 19 | darwin: output/$(BIN) 20 | windows: output/$(BIN) 21 | 22 | .PHONY: images 23 | images: 24 | mkdir -p output 25 | GO111MODULE=on GOPROXY=https://mirrors.aliyun.com/goproxy/ GOOS=$(PLATFORM) GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o output/ansibleinit $(AnsibleinitPath) 26 | docker build --no-cache -f build/ansible/Dockerfile -t ansibleinit . 27 | 28 | GO111MODULE=on GOPROXY=https://mirrors.aliyun.com/goproxy/ GOOS=$(PLATFORM) GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o output/kubernetes-operator $(OperatorPath) 29 | docker build --no-cache -f build/kube-operator/Dockerfile -t kubernetes-operator . 30 | @rm -rf output 31 | 32 | check: 33 | @find . -name vendor -prune -o -name '*.go' -exec gofmt -s -d {} + 34 | @go vet $(shell go list ./... | grep -v '/vendor/') 35 | @go test -v $(shell go list ./... | grep -v '/vendor/') 36 | 37 | vendor: 38 | dep ensure 39 | 40 | clean: 41 | @rm -rf output 42 | 43 | output/%: LDFLAGS=-s -w 44 | output/%: $(GOFILES) 45 | mkdir -p $(dir $@) 46 | GO111MODULE=on GOPROXY=https://mirrors.aliyun.com/goproxy/ GOOS=$(PLATFORM) GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o $@ 47 | -------------------------------------------------------------------------------- /scripts/deploy/deploy_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # docker releases download docs: https://kubernetes.io/docs/setup/production-environment/container-runtimes/ 4 | [ -e ./config.sh ] && . ./config.sh || exit 5 | 6 | DOCKER_BIN_DIR="../bin/${DOCKER_VER}" 7 | DOCKER_SYSTEMD_CONFIG_DIR="../systemd" 8 | DEST_SYSTEMD_DIR="/usr/lib/systemd/system" 9 | 10 | install_docker() { 11 | # Install Docker CE 12 | ## Set up the repository 13 | ### Install required packages. 14 | yum install yum-utils device-mapper-persistent-data lvm2 15 | 16 | ### Add docker repository. 17 | yum-config-manager \ 18 | --add-repo \ 19 | https://download.docker.com/linux/centos/docker-ce.repo 20 | 21 | ## Install docker ce. 22 | yum update && yum install ${DOCKER_VER} 23 | } 24 | 25 | if [ -f ${DOCKER_BIN_DIR}/dockerd ];then 26 | cp ${DOCKER_BIN_DIR}/* /usr/bin/ 27 | cp ${DOCKER_SYSTEMD_CONFIG_DIR}/docker.service ${DEST_SYSTEMD_DIR}/ 28 | else 29 | install_docker 30 | fi 31 | 32 | ## Create /etc/docker directory. 33 | mkdir /etc/docker 34 | 35 | # Setup daemon. 36 | cat > /etc/docker/daemon.json <> /etc/sysctl.conf <> /etc/modules <#--hostname_override=${LOCAL_IP}#g" ${DEST_CONFIG_DIR}/kube-proxy 60 | 61 | [ -d ${KUBE_MASTER_LOG} ] || mkdir -pv ${KUBE_MASTER_LOG} 62 | 63 | systemctl daemon-reload 64 | systemctl enable kube-proxy 65 | systemctl start kube-proxy 66 | systemctl status kube-proxy 67 | 68 | if [ $? -ne 0 ];then 69 | echo "deploy kube-proxy failed !!!" && exit 1 70 | fi 71 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/ecs/v1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | import ( 22 | internalinterfaces "github.com/gosoon/kubernetes-operator/pkg/client/informers/externalversions/internalinterfaces" 23 | ) 24 | 25 | // Interface provides access to all the informers in this group version. 26 | type Interface interface { 27 | // KubernetesClusters returns a KubernetesClusterInformer. 28 | KubernetesClusters() KubernetesClusterInformer 29 | } 30 | 31 | type version struct { 32 | factory internalinterfaces.SharedInformerFactory 33 | namespace string 34 | tweakListOptions internalinterfaces.TweakListOptionsFunc 35 | } 36 | 37 | // New returns a new Interface. 38 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 39 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 40 | } 41 | 42 | // KubernetesClusters returns a KubernetesClusterInformer. 43 | func (v *version) KubernetesClusters() KubernetesClusterInformer { 44 | return &kubernetesClusterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 45 | } 46 | -------------------------------------------------------------------------------- /scripts/config/master/apiserver: -------------------------------------------------------------------------------- 1 | ### 2 | # kubernetes system config 3 | 4 | # The following values are used to configure the kube-apiserver 5 | 6 | # The address on the local server to listen to. 7 | #KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0" 8 | 9 | # The port on the local server to listen on. 10 | # KUBE_API_PORT="--port=8080" 11 | 12 | # Comma separated list of nodes in the etcd cluster 13 | KUBE_ETCD_SERVERS="--etcd-servers=" 14 | 15 | # Address range to use for services 16 | KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=192.168.0.0/16 --secure-port=6443 --bind-address=0.0.0.0 --insecure-bind-address=0.0.0.0" 17 | 18 | # default admission control policies 19 | KUBE_ADMISSION_CONTROL="--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,Priority,ResourceQuota,NodeRestriction" 20 | 21 | # Add your own! 22 | KUBE_API_ARGS=" --storage-backend=etcd3 --storage-media-type=application/json \ 23 | --log-dir=/var/log/kubernetes \ 24 | --stderrthreshold=3 --enable-garbage-collector=true \ 25 | --anonymous-auth=false \ 26 | --authorization-mode=Node,RBAC \ 27 | --kubelet-https=true \ 28 | --enable-bootstrap-token-auth=true \ 29 | --service-cluster-ip-range=10.250.0.0/24 \ 30 | --service-account-key-file=/etc/kubernetes/ssl/ca.pem \ 31 | --tls-cert-file=/etc/kubernetes/ssl/kube-apiserver.pem \ 32 | --tls-private-key-file=/etc/kubernetes/ssl/kube-apiserver-key.pem \ 33 | --client-ca-file=/etc/kubernetes/ssl/ca.pem \ 34 | --etcd-cafile=/etc/etcd/ssl/ca.pem \ 35 | --etcd-certfile=/etc/etcd/ssl/etcd-server.pem \ 36 | --etcd-keyfile=/etc/etcd/ssl/etcd-server-key.pem \ 37 | --etcd-compaction-interval=0s \ 38 | --kubelet-client-certificate=/etc/kubernetes/ssl/apiserver-kubelet-client.pem \ 39 | --kubelet-client-key=/etc/kubernetes/ssl/apiserver-kubelet-client-key.pem" 40 | -------------------------------------------------------------------------------- /pkg/sshserver/sftp_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package sshserver 18 | 19 | import ( 20 | "testing" 21 | "time" 22 | 23 | "github.com/gosoon/kubernetes-operator/pkg/types" 24 | 25 | "github.com/stretchr/testify/assert" 26 | ) 27 | 28 | var CheckCmd = []string{"chmod +x /tmp/check.sh", "/tmp/check.sh"} 29 | 30 | func TestCopyFile(t *testing.T) { 31 | testCases := []types.SSHInfo{ 32 | { 33 | IP: "192.168.75.178", 34 | Username: "root", 35 | Port: 22, 36 | CmdList: CheckCmd, 37 | Key: "", 38 | Timeout: 35 * time.Second, 39 | }, 40 | { 41 | IP: "192.168.75.178", 42 | Username: "root", 43 | Port: 22, 44 | CmdList: CheckCmd, 45 | Key: "asdas", 46 | Timeout: 35 * time.Second, 47 | }, 48 | { 49 | IP: "", 50 | Username: "root", 51 | Port: 22, 52 | CmdList: CheckCmd, 53 | Key: "asdas", 54 | Timeout: 35 * time.Second, 55 | }, 56 | } 57 | 58 | for _, test := range testCases { 59 | t.Log(test) 60 | sshServer, err := NewSSHServer(&test) 61 | if err != nil { 62 | t.Log(err) 63 | } 64 | ch := make(chan types.PrecheckResult) 65 | sshServer.Dossh(ch) 66 | if !assert.Equal(t, nil, err) { 67 | t.Fatalf("expected: %v but get %v", nil, err) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pkg/exec/local.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package exec 18 | 19 | import ( 20 | "io" 21 | osexec "os/exec" 22 | 23 | "github.com/gosoon/glog" 24 | ) 25 | 26 | // LocalCmd wraps os/exec.Cmd, implementing interface 27 | type LocalCmd struct { 28 | *osexec.Cmd 29 | } 30 | 31 | var _ Cmd = &LocalCmd{} 32 | 33 | // LocalCmder is a factory for LocalCmd, implementing Cmder 34 | type LocalCmder struct{} 35 | 36 | var _ Cmder = &LocalCmder{} 37 | 38 | // Command returns a new exec.Cmd backed by Cmd 39 | func (c *LocalCmder) Command(name string, arg ...string) Cmd { 40 | return &LocalCmd{ 41 | Cmd: osexec.Command(name, arg...), 42 | } 43 | } 44 | 45 | // SetEnv sets env 46 | func (cmd *LocalCmd) SetEnv(env ...string) Cmd { 47 | cmd.Env = env 48 | return cmd 49 | } 50 | 51 | // SetStdin sets stdin 52 | func (cmd *LocalCmd) SetStdin(r io.Reader) Cmd { 53 | cmd.Stdin = r 54 | return cmd 55 | } 56 | 57 | // SetStdout set stdout 58 | func (cmd *LocalCmd) SetStdout(w io.Writer) Cmd { 59 | cmd.Stdout = w 60 | return cmd 61 | } 62 | 63 | // SetStderr sets stderr 64 | func (cmd *LocalCmd) SetStderr(w io.Writer) Cmd { 65 | cmd.Stderr = w 66 | return cmd 67 | } 68 | 69 | // Run runs 70 | func (cmd *LocalCmd) Run() error { 71 | glog.Infof("Running: %v %v", cmd.Path, cmd.Args) 72 | return cmd.Cmd.Run() 73 | } 74 | -------------------------------------------------------------------------------- /pkg/container/docker/pull.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package docker 18 | 19 | import ( 20 | "os/exec" 21 | "time" 22 | 23 | "github.com/gosoon/glog" 24 | ) 25 | 26 | // PullIfNotPresent will pull an image if it is not present locally 27 | // retrying up to retries times 28 | // it returns true if it attempted to pull, and any errors from pulling 29 | func PullIfNotPresent(image string, retries int) (bool, error) { 30 | cmd := exec.Command("docker", "inspect", image) 31 | if err := cmd.Run(); err != nil { 32 | glog.Infof("Image: %s present locally", image) 33 | return false, nil 34 | } 35 | return pull(image, retries) 36 | 37 | } 38 | 39 | // Pull pulls an image, retrying up to retries times 40 | func pull(image string, retries int) (bool, error) { 41 | glog.Infof("Pulling image: %s ...", image) 42 | err := exec.Command("docker", "pull", image).Run() 43 | // retry pulling up to retries times if necessary 44 | if err != nil { 45 | for i := 0; i < retries; i++ { 46 | time.Sleep(time.Second * time.Duration(i)) 47 | glog.Infof("Trying again to pull image: %s ...", image) 48 | err = exec.Command("docker", "pull", image).Run() 49 | if err == nil { 50 | break 51 | } 52 | } 53 | } 54 | 55 | if err != nil { 56 | glog.Infof("Failed to pull image: %s", image) 57 | return false, err 58 | } 59 | return true, nil 60 | } 61 | -------------------------------------------------------------------------------- /scripts/kubeconfig/generate_node_kubeconfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e ../deploy/config.sh ] && . ../deploy/config.sh || exit 1 4 | 5 | KUBE_APISERVER="https://${MASTER_VIP}:6443" 6 | CERTS_DIR="${DEPLOY_HOME_DIR}/kubernetes-operator/scripts/certs/master/output" 7 | 8 | [ -d output ] || mkdir output 9 | 10 | for node in `echo ${NODE_HOSTS} | tr ',' ' '`;do 11 | # 生成 kubelet 配置文件 12 | echo "Create kubelet kubeconfig..." 13 | kubectl config set-cluster kubernetes \ 14 | --certificate-authority=${CERTS_DIR}/ca.pem \ 15 | --embed-certs=true \ 16 | --server=${KUBE_APISERVER} \ 17 | --kubeconfig=output/kubelet-${node}.kubeconfig 18 | 19 | kubectl config set-credentials system:node:${node} \ 20 | --client-certificate=${CERTS_DIR}/kubelet.pem \ 21 | --client-key=${CERTS_DIR}/kubelet-key.pem \ 22 | --embed-certs=true \ 23 | --kubeconfig=output/kubelet-${node}.kubeconfig 24 | 25 | kubectl config set-context default \ 26 | --cluster=kubernetes \ 27 | --user=system:node:${node} \ 28 | --kubeconfig=output/kubelet-${node}.kubeconfig 29 | 30 | kubectl config use-context default --kubeconfig=output/kubelet-${node}.kubeconfig 31 | done 32 | 33 | # 生成 kube-proxy 配置文件 34 | echo "Create kube-proxy kubeconfig..." 35 | kubectl config set-cluster kubernetes \ 36 | --certificate-authority=${CERTS_DIR}/ca.pem \ 37 | --embed-certs=true \ 38 | --server=${KUBE_APISERVER} \ 39 | --kubeconfig=output/kube-proxy.kubeconfig 40 | 41 | kubectl config set-credentials "system:kube-proxy" \ 42 | --client-certificate=${CERTS_DIR}/kube-proxy.pem \ 43 | --client-key=${CERTS_DIR}/kube-proxy-key.pem \ 44 | --embed-certs=true \ 45 | --kubeconfig=output/kube-proxy.kubeconfig 46 | 47 | kubectl config set-context default \ 48 | --cluster=kubernetes \ 49 | --user=system:kube-proxy \ 50 | --kubeconfig=output/kube-proxy.kubeconfig 51 | 52 | kubectl config use-context default --kubeconfig=output/kube-proxy.kubeconfig 53 | -------------------------------------------------------------------------------- /pkg/internal/apis/config/encoding/scheme.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package encoding 18 | 19 | import ( 20 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 21 | "github.com/gosoon/kubernetes-operator/pkg/internal/apis/config" 22 | "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/kubeadm" 23 | ) 24 | 25 | // Ecsv1ToInternalCluster is convert ecsv1.KubernetesCluster to internal cluster config 26 | func Ecsv1ToInternalCluster(cluster *ecsv1.KubernetesCluster, nodeAddress string) *config.Cluster { 27 | out := &config.Cluster{ 28 | ExternalLoadBalancer: cluster.Spec.Cluster.ExternalLoadBalancer, 29 | Networking: config.Networking{ 30 | APIServerPort: kubeadm.APIServerPort, 31 | APIServerAddress: nodeAddress, 32 | PodSubnet: cluster.Spec.Cluster.PodCIDR, 33 | ServiceSubnet: cluster.Spec.Cluster.ServiceCIDR, 34 | }, 35 | KubeVersion: cluster.Spec.Cluster.KubeVersion, 36 | } 37 | 38 | var clusterNodeList []ecsv1.Node 39 | clusterNodeList = append(clusterNodeList, cluster.Spec.Cluster.NodeList...) 40 | clusterNodeList = append(clusterNodeList, cluster.Spec.Cluster.MasterList...) 41 | 42 | var workerList []config.Node 43 | for _, node := range clusterNodeList { 44 | workerList = append(workerList, config.Node{ 45 | IP: node.IP, 46 | Role: node.Role, 47 | }) 48 | } 49 | out.Nodes = workerList 50 | return out 51 | } 52 | -------------------------------------------------------------------------------- /pkg/installer/ssh/configmap.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package ssh 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/gosoon/kubernetes-operator/pkg/apis/ecs" 23 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 24 | "github.com/gosoon/kubernetes-operator/pkg/enum" 25 | "github.com/gosoon/kubernetes-operator/pkg/utils/pointer" 26 | 27 | corev1 "k8s.io/api/core/v1" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | "k8s.io/apimachinery/pkg/util/uuid" 30 | ) 31 | 32 | // newConfigMap is record all operate for echo kubernetes cluster. 33 | // TODO: set ttl for operate 34 | func newConfigMap(cluster *ecsv1.KubernetesCluster, jobName string) *corev1.ConfigMap { 35 | name := fmt.Sprintf("kube-%s-%s", cluster.Annotations[enum.Operation], string(uuid.NewUUID())[0:5]) 36 | configMap := &corev1.ConfigMap{ 37 | ObjectMeta: metav1.ObjectMeta{ 38 | Name: name, 39 | Namespace: cluster.Namespace, 40 | OwnerReferences: []metav1.OwnerReference{ 41 | { 42 | APIVersion: fmt.Sprintf("%v/v1", ecs.GroupName), 43 | Kind: Kind, 44 | Name: cluster.Name, 45 | UID: cluster.UID, 46 | Controller: pointer.BoolPtr(true), 47 | BlockOwnerDeletion: pointer.BoolPtr(true), 48 | }, 49 | }, 50 | }, 51 | Data: map[string]string{"job-name": jobName}, 52 | } 53 | return configMap 54 | } 55 | -------------------------------------------------------------------------------- /pkg/installer/cluster/context.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package cluster 18 | 19 | import ( 20 | "github.com/gosoon/kubernetes-operator/pkg/installer/cluster/constants" 21 | "github.com/gosoon/kubernetes-operator/pkg/installer/cluster/create" 22 | internalcontext "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/context" 23 | internalcreate "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/create" 24 | "google.golang.org/grpc" 25 | ) 26 | 27 | // DefaultName is the default cluster name 28 | const DefaultName = constants.DefaultClusterName 29 | 30 | // Context is used to create / manipulate kubernetes-in-docker clusters 31 | // See: NewContext() 32 | type Context struct { 33 | // the internal context type, shared between implementations of more 34 | // advanced methods like create 35 | ic *internalcontext.Context 36 | } 37 | 38 | // NewContext returns a new cluster management context 39 | // if name is "" the default name will be used (constants.DefaultClusterName) 40 | func NewContext(name string, server *grpc.Server, port string) *Context { 41 | // wrap a new internal context 42 | return &Context{ 43 | ic: internalcontext.NewContext(name, server, port), 44 | } 45 | } 46 | 47 | // Create provisions and starts a kubernetes-in-docker cluster 48 | func (c *Context) Create(options ...create.ClusterOption) error { 49 | return internalcreate.Cluster(c.ic, options...) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/installer/grpc/server/install.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package server 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/gosoon/glog" 23 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 24 | "github.com/gosoon/kubernetes-operator/pkg/installer/util/protobuf" 25 | ) 26 | 27 | // ClusterNew is creating a new cluster 28 | func (inst *installer) ClusterNew(cluster *ecsv1.KubernetesCluster) error { 29 | clusterRequest, err := protobuf.ClusterConvertToProtobuf(cluster) 30 | if err != nil { 31 | glog.Errorf("clusterRequest convert to protobuf failed with:%v", err) 32 | return err 33 | } 34 | 35 | _, err = inst.InstallCluster(context.Background(), clusterRequest) 36 | if err != nil { 37 | glog.Errorf("installCluster failed with %v", err) 38 | return err 39 | } 40 | 41 | return nil 42 | } 43 | 44 | // ClusterScaleUp is scale up a cluster node 45 | func (inst *installer) ClusterScaleUp(cluster *ecsv1.KubernetesCluster, scaleUpNodeList []ecsv1.Node) error { 46 | // TODO 47 | return nil 48 | } 49 | 50 | // ClusterScaleDown is scale down a cluster node 51 | func (inst *installer) ClusterScaleDown(cluster *ecsv1.KubernetesCluster, scaleDownNodeList []ecsv1.Node) error { 52 | // TODO 53 | return nil 54 | } 55 | 56 | // ClusterTerminating is delete a cluster 57 | func (inst *installer) ClusterTerminating(cluster *ecsv1.KubernetesCluster) error { 58 | // TODO 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /pkg/utils/pointer/pointer_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package pointer 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/stretchr/testify/assert" 23 | ) 24 | 25 | func TestInt32Ptr(t *testing.T) { 26 | testCases := []struct { 27 | int32Value int32 28 | }{ 29 | { 30 | int32Value: int32(1), 31 | }, 32 | { 33 | int32Value: int32(-1), 34 | }, 35 | } 36 | 37 | for _, test := range testCases { 38 | ptr := Int32Ptr(test.int32Value) 39 | if !assert.Equal(t, &test.int32Value, ptr) { 40 | t.Fatalf("expected: %v but get %v", &test.int32Value, ptr) 41 | } 42 | } 43 | } 44 | 45 | func TestInt64Ptr(t *testing.T) { 46 | testCases := []struct { 47 | int64Value int64 48 | }{ 49 | { 50 | int64Value: int64(1), 51 | }, 52 | { 53 | int64Value: int64(-1), 54 | }, 55 | } 56 | 57 | for _, test := range testCases { 58 | ptr := Int64Ptr(test.int64Value) 59 | if !assert.Equal(t, &test.int64Value, ptr) { 60 | t.Fatalf("expected: %v but get %v", &test.int64Value, ptr) 61 | } 62 | } 63 | } 64 | 65 | func TestBoolPtr(t *testing.T) { 66 | testCases := []struct { 67 | boolValue bool 68 | }{ 69 | { 70 | boolValue: true, 71 | }, 72 | { 73 | boolValue: false, 74 | }, 75 | } 76 | 77 | for _, test := range testCases { 78 | ptr := BoolPtr(test.boolValue) 79 | if !assert.Equal(t, &test.boolValue, ptr) { 80 | t.Fatalf("expected: %v but get %v", &test.boolValue, ptr) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var scheme = runtime.NewScheme() 31 | var codecs = serializer.NewCodecFactory(scheme) 32 | var parameterCodec = runtime.NewParameterCodec(scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | ecsv1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package scheme 20 | 21 | import ( 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 27 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 28 | ) 29 | 30 | var Scheme = runtime.NewScheme() 31 | var Codecs = serializer.NewCodecFactory(Scheme) 32 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | ecsv1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(Scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/internal/cluster/create/actions/waitforready/waitforready.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package waitforready 18 | 19 | import ( 20 | "fmt" 21 | "time" 22 | 23 | "github.com/gosoon/kubernetes-operator/pkg/installer/cluster/nodes" 24 | "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/create/actions" 25 | ) 26 | 27 | // Action implements an action for waiting for the cluster to be ready 28 | type Action struct { 29 | waitTime time.Duration 30 | } 31 | 32 | // NewAction returns a new action for waiting for the cluster to be ready 33 | func NewAction(waitTime time.Duration) actions.Action { 34 | return &Action{ 35 | waitTime: waitTime, 36 | } 37 | } 38 | 39 | // Execute runs the action 40 | func (a *Action) Execute(ctx *actions.ActionContext) error { 41 | // skip entirely if the wait time is 0 42 | if a.waitTime == time.Duration(0) { 43 | return nil 44 | } 45 | ctx.Status.Start( 46 | fmt.Sprintf( 47 | "Waiting ≤ %s for control-plane = Ready", 48 | formatDuration(a.waitTime), 49 | ), 50 | ) 51 | 52 | // Wait for the nodes to reach Ready status. 53 | startTime := time.Now() 54 | isReady := nodes.WaitForReady(startTime.Add(a.waitTime)) 55 | if !isReady { 56 | ctx.Status.End(false) 57 | fmt.Println(" • WARNING: Timed out waiting for Ready ⚠️") 58 | return nil 59 | } 60 | // mark success 61 | ctx.Status.End(true) 62 | fmt.Printf(" • Ready after %s 💚\n", formatDuration(time.Since(startTime))) 63 | return nil 64 | } 65 | 66 | func formatDuration(duration time.Duration) string { 67 | return duration.Round(time.Second).String() 68 | } 69 | -------------------------------------------------------------------------------- /pkg/types/ecsclient.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package types 18 | 19 | import ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 20 | 21 | // EcsClient xxx 22 | type EcsClient struct { 23 | Name string `json:"name"` 24 | Namespace string `json:"namespace"` 25 | Region string `json:"region"` 26 | TimeoutMins string `json:"timeoutMins"` 27 | ClusterType string `json:"clusterType"` 28 | PodCIDR string `json:"podCIDR"` 29 | ServiceCIDR string `json:"serviceCIDR"` 30 | MasterList []ecsv1.Node `json:"masterList"` 31 | ExternalLoadBalancer string `json:"externalLoadBalancer"` 32 | NodeList []ecsv1.Node `json:"nodeList"` 33 | EtcdList []ecsv1.Node `json:"etcdList"` 34 | KubeVersion string `json:"kubeVersion"` 35 | 36 | // PrivateSSHKey,because of ssh private key has multiple special characters, use base64 encode in it 37 | PrivateSSHKey string `json:"privateSSHKey"` 38 | Retry bool `json:"retry"` 39 | } 40 | 41 | // Callback xxx 42 | type Callback struct { 43 | Name string `json:"name"` 44 | Namespace string `json:"namespace"` 45 | Region string `json:"region"` 46 | MasterList []ecsv1.Node `json:"masterList"` 47 | NodeList []ecsv1.Node `json:"nodeList"` 48 | EtcdList []ecsv1.Node `json:"etcdList"` 49 | KubeConfig string `json:"kubeconfig"` 50 | Success bool `json:"success"` 51 | Message string `json:"message"` 52 | } 53 | -------------------------------------------------------------------------------- /scripts/deploy/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export LC_ALL=en_US.UTF-8 4 | export LANG=en_US.UTF-8 5 | 6 | ROOT=`cd $(dirname $0); pwd` 7 | DEPLOY_MASTER_LOG="/var/log/deploy_master.log" 8 | DEPLOY_NODE_LOG="/var/log/deploy_node.log" 9 | DEPLOY_ETCD_LOG="/var/log/deploy_etcd.log" 10 | DEPLOY_MASTER_FINISHED="/var/log/master_deployed" 11 | DEPLOY_NODE_FINISHED="/var/log/node_deployed" 12 | DEPLOY_ETCD_FINISHED="/var/log/etcd_deployed" 13 | 14 | master() { 15 | echo -n "starting deploy master... " 16 | [ -f ${DEPLOY_MASTER_FINISHED} ] && { echo "master is deployed"; exit 1; } || > ${DEPLOY_MASTER_LOG} 17 | [ -f base_env_01.sh ] && bash -x base_env_01.sh &>> ${DEPLOY_MASTER_LOG} || exit 1 18 | [ -f deploy_master.sh ] && bash -x deploy_master.sh &>> ${DEPLOY_MASTER_LOG} || exit 1 19 | [ -f deploy_coredns.sh ] && bash -x deploy_coredns.sh &>> ${DEPLOY_MASTER_LOG} || exit 1 20 | [ -f deploy_calico.sh ] && bash -x deploy_calico.sh &>> ${DEPLOY_MASTER_LOG} || exit 1 21 | touch ${DEPLOY_MASTER_FINISHED} 22 | } 23 | 24 | node() { 25 | echo -n "starting deploy node... " 26 | [ -f ${DEPLOY_NODE_FINISHED} ] && { echo "node is deployed"; exit 1; } || > ${DEPLOY_NODE_LOG} 27 | [ -f base_env_01.sh ] && bash -x base_env_01.sh &>> ${DEPLOY_NODE_LOG} || exit 1 28 | [ -f deploy_docker.sh ] && bash -x deploy_docker.sh &>> ${DEPLOY_NODE_LOG} || exit 1 29 | [ -f deploy_kubelet.sh ] && bash -x deploy_kubelet.sh &>> ${DEPLOY_NODE_LOG} || exit 1 30 | [ -f deploy_kube_proxy.sh ] && bash -x deploy_kube_proxy.sh &>> ${DEPLOY_NODE_LOG} || exit 1 31 | touch ${DEPLOY_NODE_FINISHED} 32 | } 33 | 34 | etcd() { 35 | echo -n "starting deploy etcd... " 36 | [ -f ${DEPLOY_ETCD_FINISHED} ] && { echo "etcd is deployed"; exit 1; } || > ${DEPLOY_ETCD_LOG} 37 | [ -f base_env_01.sh ] && bash -x base_env_01.sh &>> ${DEPLOY_ETCD_LOG} || exit 1 38 | [ -f deploy_etcd.sh ] && bash -x deploy_etcd.sh &>> ${DEPLOY_ETCD_LOG} || exit 1 39 | touch ${DEPLOY_ETCD_FINISHED} 40 | } 41 | 42 | 43 | case "$1" in 44 | master) 45 | master 46 | ;; 47 | 48 | node) 49 | node 50 | ;; 51 | 52 | etcd) 53 | etcd 54 | ;; 55 | 56 | *) 57 | echo "Usage: $0 {master|node|etcd}" 58 | exit 1 59 | esac 60 | -------------------------------------------------------------------------------- /pkg/kuberesource/resourcelock.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package kuberesource 18 | 19 | import ( 20 | "os" 21 | 22 | "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned/scheme" 23 | "github.com/gosoon/kubernetes-operator/pkg/controller" 24 | 25 | "github.com/gosoon/glog" 26 | v1 "k8s.io/api/core/v1" 27 | "k8s.io/apimachinery/pkg/util/uuid" 28 | "k8s.io/client-go/kubernetes" 29 | typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" 30 | "k8s.io/client-go/tools/leaderelection/resourcelock" 31 | "k8s.io/client-go/tools/record" 32 | ) 33 | 34 | func NewResourceLock(kubeClient *kubernetes.Clientset) (resourcelock.Interface, error) { 35 | // init eventRecorder 36 | eventBroadcaster := record.NewBroadcaster() 37 | eventRecorder := eventBroadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: controller.ComponentName}) 38 | eventBroadcaster.StartLogging(glog.Infof) 39 | eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeClient.CoreV1().Events("")}) 40 | 41 | // init host identity 42 | id, err := os.Hostname() 43 | if err != nil { 44 | glog.Errorf("get hostname error: %v", err) 45 | return nil, err 46 | } 47 | id = id + "_" + string(uuid.NewUUID()) 48 | 49 | rl, err := resourcelock.New("endpoints", 50 | "kube-system", 51 | controller.ComponentName, 52 | kubeClient.CoreV1(), 53 | kubeClient.CoordinationV1(), 54 | resourcelock.ResourceLockConfig{ 55 | Identity: id, 56 | EventRecorder: eventRecorder, 57 | }) 58 | 59 | if err != nil { 60 | glog.Errorf("error creating lock: %v", err) 61 | return nil, err 62 | } 63 | return rl, nil 64 | } 65 | -------------------------------------------------------------------------------- /cmd/installer/grpc/agent/app/app.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package app 18 | 19 | import ( 20 | "net" 21 | "time" 22 | 23 | "github.com/gosoon/glog" 24 | "github.com/spf13/cobra" 25 | "google.golang.org/grpc" 26 | 27 | installerv1 "github.com/gosoon/kubernetes-operator/pkg/apis/installer/v1" 28 | grpcagent "github.com/gosoon/kubernetes-operator/pkg/installer/grpc/agent" 29 | ) 30 | 31 | type Flagpole struct { 32 | Config string 33 | Retain bool 34 | Wait time.Duration 35 | Port string 36 | } 37 | 38 | // NewServerCommand returns a new cobra.Command for kube-on-kube server 39 | func NewServerCommand() *cobra.Command { 40 | flags := &Flagpole{} 41 | cmd := &cobra.Command{ 42 | Args: cobra.NoArgs, 43 | Use: "cluster", 44 | Short: "Creates a local Kubernetes cluster", 45 | Long: "Creates a local Kubernetes cluster ", 46 | Run: func(cmd *cobra.Command, args []string) { 47 | run(flags) 48 | }, 49 | } 50 | cmd.Flags().DurationVar(&flags.Wait, "wait", time.Duration(0), "Wait for control plane node to be ready (default 0s)") 51 | cmd.Flags().StringVar(&flags.Port, "port", "10023", "installer grpc agent port(default 10023)") 52 | return cmd 53 | } 54 | 55 | func run(flags *Flagpole) { 56 | // start grpc server 57 | l, err := net.Listen("tcp", ":"+flags.Port) 58 | if err != nil { 59 | glog.Fatalf("failed to listen: %v", err) 60 | } 61 | server := grpc.NewServer() 62 | 63 | agent := grpcagent.NewAgent(&grpcagent.Options{ 64 | Port: flags.Port, 65 | Server: server, 66 | }) 67 | 68 | // register grpc server 69 | installerv1.RegisterInstallerServer(server, agent) 70 | glog.Fatal(server.Serve(l)) 71 | } 72 | -------------------------------------------------------------------------------- /pkg/container/docker/run.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package docker 18 | 19 | import ( 20 | "github.com/gosoon/glog" 21 | "github.com/gosoon/kubernetes-operator/pkg/exec" 22 | ) 23 | 24 | // RunOpt is an option for Run 25 | type RunOpt func(*runOpts) *runOpts 26 | 27 | // actual options struct 28 | type runOpts struct { 29 | RunArgs []string 30 | ContainerArgs []string 31 | } 32 | 33 | // WithRunArgs sets the args for docker run 34 | // as in the args portion of `docker run args... image containerArgs...` 35 | func WithRunArgs(args ...string) RunOpt { 36 | return func(r *runOpts) *runOpts { 37 | r.RunArgs = args 38 | return r 39 | } 40 | } 41 | 42 | // WithContainerArgs sets the args to the container 43 | // as in the containerArgs portion of `docker run args... image containerArgs...` 44 | // NOTE: this is only the args portion before the image 45 | func WithContainerArgs(args ...string) RunOpt { 46 | return func(r *runOpts) *runOpts { 47 | r.ContainerArgs = args 48 | return r 49 | } 50 | } 51 | 52 | // Run creates a container with "docker run", with some error handling 53 | func Run(image string, opts ...RunOpt) error { 54 | o := &runOpts{} 55 | for _, opt := range opts { 56 | o = opt(o) 57 | } 58 | 59 | // construct the actual docker run argv 60 | args := []string{"run"} 61 | args = append(args, o.RunArgs...) 62 | args = append(args, image) 63 | cmd := exec.Command("docker", args...) 64 | 65 | output, err := exec.CombinedOutputLines(cmd) 66 | if err != nil { 67 | // log error output if there was any 68 | for _, line := range output { 69 | glog.Error(line) 70 | } 71 | return err 72 | } 73 | return nil 74 | } 75 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by informer-gen. DO NOT EDIT. 18 | 19 | package externalversions 20 | 21 | import ( 22 | "fmt" 23 | 24 | v1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 25 | schema "k8s.io/apimachinery/pkg/runtime/schema" 26 | cache "k8s.io/client-go/tools/cache" 27 | ) 28 | 29 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 30 | // sharedInformers based on type 31 | type GenericInformer interface { 32 | Informer() cache.SharedIndexInformer 33 | Lister() cache.GenericLister 34 | } 35 | 36 | type genericInformer struct { 37 | informer cache.SharedIndexInformer 38 | resource schema.GroupResource 39 | } 40 | 41 | // Informer returns the SharedIndexInformer. 42 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 43 | return f.informer 44 | } 45 | 46 | // Lister returns the GenericLister. 47 | func (f *genericInformer) Lister() cache.GenericLister { 48 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 49 | } 50 | 51 | // ForResource gives generic access to a shared informer of the matching type 52 | // TODO extend this to unknown resources with a client pool 53 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 54 | switch resource { 55 | // Group=ecs.yun.com, Version=v1 56 | case v1.SchemeGroupVersion.WithResource("kubernetesclusters"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Ecs().V1().KubernetesClusters().Informer()}, nil 58 | 59 | } 60 | 61 | return nil, fmt.Errorf("no informer found for %v", resource) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/server/serving.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package server 18 | 19 | import ( 20 | "net/http" 21 | "time" 22 | 23 | ctrl "github.com/gosoon/kubernetes-operator/pkg/server/controller" 24 | "github.com/gosoon/kubernetes-operator/pkg/server/controller/cluster" 25 | "github.com/gosoon/kubernetes-operator/pkg/server/service" 26 | 27 | "github.com/gorilla/mux" 28 | ) 29 | 30 | type Server interface { 31 | http.Handler 32 | ListenAndServe() error 33 | } 34 | 35 | type Options struct { 36 | CtrlOptions *ctrl.Options 37 | ListenAddr string 38 | } 39 | 40 | type server struct { 41 | opt Options 42 | router *mux.Router 43 | } 44 | 45 | func New(opt Options) Server { 46 | // init service 47 | options := &service.Options{ 48 | KubernetesClusterClientset: opt.CtrlOptions.KubernetesClusterClientset, 49 | KubeClientset: opt.CtrlOptions.KubeClientset, 50 | } 51 | 52 | opt.CtrlOptions.Service = service.New(options) 53 | 54 | router := mux.NewRouter().StrictSlash(true) 55 | cluster.New(opt.CtrlOptions).Register(router) 56 | 57 | return &server{ 58 | opt: opt, 59 | router: router, 60 | } 61 | } 62 | 63 | func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 64 | s.router.ServeHTTP(w, r) 65 | } 66 | 67 | func (s *server) ListenAndServe() error { 68 | server := &http.Server{ 69 | Handler: s.router, 70 | Addr: s.opt.ListenAddr, 71 | // Good practice: enforce timeouts for servers you create! 72 | WriteTimeout: 15 * time.Second, 73 | ReadTimeout: 15 * time.Second, 74 | MaxHeaderBytes: 1 << 20, 75 | } 76 | if err := server.ListenAndServe(); err != nil { 77 | return err 78 | } 79 | return nil 80 | } 81 | -------------------------------------------------------------------------------- /pkg/server/service/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package service 18 | 19 | import ( 20 | "context" 21 | 22 | clientset "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned" 23 | "github.com/gosoon/kubernetes-operator/pkg/types" 24 | 25 | "k8s.io/client-go/kubernetes" 26 | ) 27 | 28 | type Options struct { 29 | KubernetesClusterClientset clientset.Interface 30 | KubeClientset kubernetes.Interface 31 | } 32 | 33 | type service struct { 34 | opt *Options 35 | } 36 | 37 | func New(opt *Options) Interface { 38 | return &service{opt: opt} 39 | } 40 | 41 | type Interface interface { 42 | // cluster 43 | CreateCluster(ctx context.Context, region string, namespace string, name string, clusterInfo *types.EcsClient) error 44 | DeleteCluster(ctx context.Context, region string, namespace string, name string, clusterInfo *types.EcsClient) error 45 | 46 | // scale 47 | ScaleUp(ctx context.Context, region string, namespace string, name string, clusterInfo *types.EcsClient) error 48 | ScaleDown(ctx context.Context, region string, namespace string, name string, clusterInfo *types.EcsClient) error 49 | 50 | // callback 51 | CreateClusterCallback(ctx context.Context, region string, namespace string, name string, result *types.Callback) error 52 | ScaleUpCallback(ctx context.Context, region string, namespace string, name string, result *types.Callback) error 53 | ScaleDownCallback(ctx context.Context, region string, namespace string, name string, result *types.Callback) error 54 | DeleteClusterCallback(ctx context.Context, region string, namespace string, name string, result *types.Callback) error 55 | 56 | // logs 57 | GetClusterOperationLogs(ctx context.Context, region string, namespace string, name string) (string, error) 58 | } 59 | -------------------------------------------------------------------------------- /pkg/installer/grpc/agent/server_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package agent 18 | 19 | import ( 20 | "net" 21 | "testing" 22 | 23 | "github.com/gosoon/glog" 24 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 25 | installerv1 "github.com/gosoon/kubernetes-operator/pkg/apis/installer/v1" 26 | 27 | "google.golang.org/grpc" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | ) 30 | 31 | const port = "10023" 32 | 33 | func TestInstallCluster(t *testing.T) { 34 | // start grpc server 35 | l, err := net.Listen("tcp", ":"+"10023") 36 | if err != nil { 37 | glog.Fatalf("failed to listen: %v", err) 38 | } 39 | server := grpc.NewServer() 40 | agent := NewAgent(&Options{ 41 | Server: server, 42 | Port: port, 43 | }) 44 | 45 | // register grpc server 46 | installerv1.RegisterInstallerServer(server, agent) 47 | 48 | go func() { 49 | glog.Fatal(server.Serve(l)) 50 | }() 51 | 52 | kubernetesCluster := &ecsv1.KubernetesCluster{ 53 | TypeMeta: metav1.TypeMeta{ 54 | Kind: "KubernetesCluster", 55 | APIVersion: "ecs.yun.com/v1", 56 | }, 57 | ObjectMeta: metav1.ObjectMeta{ 58 | Name: "test", 59 | Namespace: "default", 60 | }, 61 | Spec: ecsv1.KubernetesClusterSpec{ 62 | Cluster: ecsv1.Cluster{ 63 | ClusterType: ecsv1.KubernetesClusterType, 64 | PodCIDR: "192.168.0.0/16", 65 | ServiceCIDR: "10.233.0.0/18", 66 | MasterList: []ecsv1.Node{{IP: "192.168.72.224", Role: ecsv1.ControlPlaneRole}}, 67 | ExternalLoadBalancer: "127.0.0.1", 68 | Region: "default", 69 | KubeVersion: "v1.15.3", 70 | }, 71 | }, 72 | } 73 | 74 | err = agent.ClusterNew(kubernetesCluster) 75 | if err != nil { 76 | glog.Error(err) 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /pkg/installer/grpc/agent/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package agent 18 | 19 | import ( 20 | "sort" 21 | 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 23 | ) 24 | 25 | type nodeList []ecsv1.Node 26 | 27 | func (n nodeList) Less(i, j int) bool { return n[i].IP < n[j].IP } 28 | func (n nodeList) Swap(i, j int) { n[i], n[j] = n[j], n[i] } 29 | func (n nodeList) Len() int { return len(n) } 30 | 31 | // injectClusterNodeRole is set role for cluster all nodes 32 | // when installing a cluster, kubeadm first install a controlplane,then secondarycontrolplane should join controlplane, 33 | // the workers node also join controlplane 34 | // ps: 35 | // this action is implementation in server at first,because proto3 not support type define alias,the NodeRole is a NodeRole type not string 36 | // in order to reduce complexity so can do it in agent 37 | func injectClusterNodeRole(cluster *ecsv1.KubernetesCluster) *ecsv1.KubernetesCluster { 38 | // set master role 39 | // grpc server select some node and set to ControlPlaneRole,SecondaryControlPlaneRole,WorkerRole 40 | if len(cluster.Spec.Cluster.MasterList) > 0 { 41 | masterList := cluster.Spec.Cluster.MasterList 42 | sort.Sort(nodeList(masterList)) 43 | for idx, master := range cluster.Spec.Cluster.MasterList { 44 | cluster.Spec.Cluster.MasterList[idx].Role = ecsv1.SecondaryControlPlaneRole 45 | if master.IP == masterList[0].IP { 46 | cluster.Spec.Cluster.MasterList[idx].Role = ecsv1.ControlPlaneRole 47 | } 48 | } 49 | } 50 | 51 | // set node role,default all node is worker 52 | if len(cluster.Spec.Cluster.NodeList) > 0 { 53 | for idx := range cluster.Spec.Cluster.NodeList { 54 | cluster.Spec.Cluster.NodeList[idx].Role = ecsv1.WorkerRole 55 | } 56 | } 57 | 58 | return cluster 59 | } 60 | -------------------------------------------------------------------------------- /pkg/controller/cluster_precheck_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "testing" 21 | 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 23 | ecsfake "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned/fake" 24 | informers "github.com/gosoon/kubernetes-operator/pkg/client/informers/externalversions" 25 | "github.com/gosoon/kubernetes-operator/pkg/enum" 26 | 27 | "github.com/stretchr/testify/assert" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | "k8s.io/client-go/kubernetes/fake" 30 | "k8s.io/kubernetes/pkg/controller" 31 | ) 32 | 33 | func TestProcessClusterPrecheck(t *testing.T) { 34 | fakeClient := fake.NewSimpleClientset() 35 | kubernetesClusterClient := ecsfake.NewSimpleClientset() 36 | informerFactory := informers.NewSharedInformerFactory(kubernetesClusterClient, controller.NoResyncPeriodFunc()) 37 | ecsv1Controller := NewController(fakeClient, kubernetesClusterClient, 38 | informerFactory.Ecs().V1().KubernetesClusters()) 39 | ecsv1Controller.kubernetesClusterSynced = alwaysReady 40 | 41 | testCases := []*ecsv1.KubernetesCluster{ 42 | &ecsv1.KubernetesCluster{ 43 | ObjectMeta: metav1.ObjectMeta{ 44 | Name: "test-1", 45 | }, 46 | Status: ecsv1.KubernetesClusterStatus{ 47 | Phase: enum.Running, 48 | }, 49 | }, 50 | &ecsv1.KubernetesCluster{ 51 | ObjectMeta: metav1.ObjectMeta{ 52 | Name: "test-2", 53 | }, 54 | Status: ecsv1.KubernetesClusterStatus{ 55 | Phase: enum.Failed, 56 | }, 57 | }, 58 | } 59 | 60 | for _, test := range testCases { 61 | _, err := kubernetesClusterClient.EcsV1().KubernetesClusters("").Create(test) 62 | if err != nil { 63 | t.Fatalf("error injecting ecs add: %v", err) 64 | } 65 | err = ecsv1Controller.processClusterPrecheck(test) 66 | if !assert.Equal(t, nil, err) { 67 | t.Fatalf("expected: %v but get %v", nil, err) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pkg/internal/cluster/create/actions/installcni/cni.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package installcni 18 | 19 | import ( 20 | "bytes" 21 | "html/template" 22 | "strings" 23 | 24 | "github.com/gosoon/kubernetes-operator/pkg/exec" 25 | "github.com/gosoon/kubernetes-operator/pkg/internal/cluster/create/actions" 26 | "github.com/pkg/errors" 27 | ) 28 | 29 | type action struct{} 30 | 31 | // NewAction returns a new action for installing default CNI 32 | func NewAction() actions.Action { 33 | return &action{} 34 | } 35 | 36 | // Execute runs the action 37 | func (a *action) Execute(ctx *actions.ActionContext) error { 38 | ctx.Status.Start("Installing CNI") 39 | defer ctx.Status.End(false) 40 | 41 | // read the manifest from the node 42 | var raw bytes.Buffer 43 | if err := exec.Command("cat", "/tmp/install/kubernetes/manifests/default-cni.yaml").SetStdout(&raw).Run(); err != nil { 44 | return errors.Wrap(err, "failed to read CNI manifest") 45 | } 46 | manifest := raw.String() 47 | 48 | // note:the default networking is calico, version is v3.8 49 | if strings.Contains(manifest, "networking manifest") { 50 | t, err := template.New("cni-manifest").Parse(manifest) 51 | if err != nil { 52 | return errors.Wrap(err, "failed to parse CNI manifest template") 53 | } 54 | var out bytes.Buffer 55 | err = t.Execute(&out, &struct { 56 | PodSubnet string 57 | }{ 58 | PodSubnet: ctx.Cluster.Config.Networking.PodSubnet, 59 | }) 60 | if err != nil { 61 | return errors.Wrap(err, "failed to execute CNI manifest template") 62 | } 63 | manifest = out.String() 64 | } 65 | 66 | // install the manifest 67 | if err := exec.Command( 68 | "kubectl", "create", "--kubeconfig=/etc/kubernetes/admin.conf", 69 | "-f", "-", 70 | ).SetStdin(strings.NewReader(manifest)).Run(); err != nil { 71 | return errors.Wrap(err, "failed to apply overlay network") 72 | } 73 | 74 | // mark success 75 | ctx.Status.End(true) 76 | return nil 77 | } 78 | -------------------------------------------------------------------------------- /pkg/installer/cluster/nodes/systemd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nodes 18 | 19 | const ( 20 | // KubeletServicePath is systemd service path 21 | KubeletServicePath = "/usr/lib/systemd/system/kubelet.service" 22 | 23 | KubeletServiceConfigDir = "/usr/lib/systemd/system/kubelet.service.d/" 24 | KubeletServicrDefaultConfig = "/etc/sysconfig/kubelet" 25 | ) 26 | 27 | // slightly modified from 28 | // https://github.com/kubernetes/kubernetes/blob/ba8fcafaf8c502a454acd86b728c857932555315/build/debs/kubelet.service 29 | const KubeletServiceContents = `[Unit] 30 | Description=kubelet: The Kubernetes Node Agent 31 | Documentation=http://kubernetes.io/docs/ 32 | 33 | [Service] 34 | ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd 35 | Restart=always 36 | StartLimitInterval=0 37 | RestartSec=10 38 | 39 | 40 | [Install] 41 | WantedBy=multi-user.target 42 | ` 43 | 44 | // https://github.com/kubernetes/kubernetes/blob/ba8fcafaf8c502a454acd86b728c857932555315/build/debs/10-kubeadm.conf 45 | const Kubeadm10conf = `# Note: This dropin only works with kubeadm and kubelet v1.11+ 46 | [Service] 47 | Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf" 48 | Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml" 49 | # This is a file that "kubeadm init" and "kubeadm join" generates at runtime, populating the KUBELET_KUBEADM_ARGS variable dynamically 50 | EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env 51 | # This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably, the user should use 52 | # the .NodeRegistration.KubeletExtraArgs object in the configuration files instead. KUBELET_EXTRA_ARGS should be sourced from this file. 53 | EnvironmentFile=-/etc/default/kubelet 54 | ExecStart= 55 | ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS 56 | ` 57 | -------------------------------------------------------------------------------- /test/create_ecs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | region="default" 4 | name="test-cluster" 5 | request_body=$(cat< timeout { 68 | curCluster = curCluster.DeepCopy() 69 | // update kubernetesCluster annotation operation and status 70 | curCluster.Status.Reason = fmt.Sprintf("the [%v] job running timeout(>%vs)", oldOperation, timeout) 71 | curCluster.Status.Phase = enum.Failed 72 | curCluster.Status.LastTransitionTime = metav1.Now() 73 | _, err := inst.opt.KubernetesClusterClientset.EcsV1().KubernetesClusters(namespace).UpdateStatus(curCluster) 74 | if err != nil { 75 | glog.Errorf("jobTTLTimeout update %s/%s cluster status failed with:%v", namespace, name, err) 76 | } 77 | stopCh <- struct{}{} 78 | return 79 | } 80 | }, period, stopCh) 81 | } 82 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/clientset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package versioned 20 | 21 | import ( 22 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned/typed/ecs/v1" 23 | discovery "k8s.io/client-go/discovery" 24 | rest "k8s.io/client-go/rest" 25 | flowcontrol "k8s.io/client-go/util/flowcontrol" 26 | ) 27 | 28 | type Interface interface { 29 | Discovery() discovery.DiscoveryInterface 30 | EcsV1() ecsv1.EcsV1Interface 31 | } 32 | 33 | // Clientset contains the clients for groups. Each group has exactly one 34 | // version included in a Clientset. 35 | type Clientset struct { 36 | *discovery.DiscoveryClient 37 | ecsV1 *ecsv1.EcsV1Client 38 | } 39 | 40 | // EcsV1 retrieves the EcsV1Client 41 | func (c *Clientset) EcsV1() ecsv1.EcsV1Interface { 42 | return c.ecsV1 43 | } 44 | 45 | // Discovery retrieves the DiscoveryClient 46 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 47 | if c == nil { 48 | return nil 49 | } 50 | return c.DiscoveryClient 51 | } 52 | 53 | // NewForConfig creates a new Clientset for the given config. 54 | func NewForConfig(c *rest.Config) (*Clientset, error) { 55 | configShallowCopy := *c 56 | if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { 57 | configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) 58 | } 59 | var cs Clientset 60 | var err error 61 | cs.ecsV1, err = ecsv1.NewForConfig(&configShallowCopy) 62 | if err != nil { 63 | return nil, err 64 | } 65 | 66 | cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) 67 | if err != nil { 68 | return nil, err 69 | } 70 | return &cs, nil 71 | } 72 | 73 | // NewForConfigOrDie creates a new Clientset for the given config and 74 | // panics if there is an error in the config. 75 | func NewForConfigOrDie(c *rest.Config) *Clientset { 76 | var cs Clientset 77 | cs.ecsV1 = ecsv1.NewForConfigOrDie(c) 78 | 79 | cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) 80 | return &cs 81 | } 82 | 83 | // New creates a new Clientset for the given RESTClient. 84 | func New(c rest.Interface) *Clientset { 85 | var cs Clientset 86 | cs.ecsV1 = ecsv1.New(c) 87 | 88 | cs.DiscoveryClient = discovery.NewDiscoveryClient(c) 89 | return &cs 90 | } 91 | -------------------------------------------------------------------------------- /scripts/deploy/deploy_kubelet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e /etc/init.d/functions ] && . /etc/init.d/functions || exit 4 | [ -e ./config.sh ] && . ./config.sh || exit 5 | 6 | KUBE_NODE_BIN_DIR="../bin/${KUBERNETES_VER}" 7 | KUBE_NODE_CONFIG_DIR="../config/node" 8 | KUBE_NODE_SYSTEMD_CONFIG_DIR="../systemd" 9 | CERTS_DIR="../certs" 10 | KUBECONFIG_DIR="../kubeconfig/" 11 | GENERATE_CERTS_FILE="../certs/node" 12 | GENERATE_KUBECONFIG_FILE="../kubeconfig" 13 | 14 | DEST_CERTS_DIR="/etc/kubernetes/ssl" 15 | DEST_SYSTEMD_DIR="/usr/lib/systemd/system" 16 | DEST_CONFIG_DIR="/etc/kubernetes" 17 | KUBE_MASTER_LOG="/var/log/kubernetes" 18 | 19 | cp ${KUBE_NODE_BIN_DIR}/kubelet /usr/bin/ && \ 20 | chmod +x /usr/bin/kubelet 21 | cp ${KUBE_NODE_SYSTEMD_CONFIG_DIR}/kubelet.service ${DEST_SYSTEMD_DIR} 22 | 23 | [ -d ${DEST_CONFIG_DIR} ] || mkdir ${DEST_CONFIG_DIR} 24 | cp ${KUBE_NODE_CONFIG_DIR}/{config,config.yaml,kubelet} ${DEST_CONFIG_DIR}/ 25 | 26 | # update config master ip 27 | sed -i -e "s#--master=https://:6443#--master=https://${MASTER_VIP}:6443#g" ${DEST_CONFIG_DIR}/config 28 | sed -i -e "s#--hostname_override=#--hostname_override=${LOCAL_IP}#g" ${DEST_CONFIG_DIR}/kubelet 29 | sed -i -e "s#hostnameOverride: #hostnameOverride: ${LOCAL_IP}#g" ${DEST_CONFIG_DIR}/config.yaml 30 | 31 | # scp ssl from master 32 | for master in `echo ${MASTER_HOSTS} | tr ',' ' '`;do 33 | scp -i ${DEPLOY_HOME_DIR}/private-key root@${master}:${DEST_CERTS_DIR}/{ca.pem,ca-key.pem} ${DEST_CERTS_DIR}/ 34 | [ $? -eq 0 ] && break 35 | done 36 | 37 | # generate ssl 38 | #cd ${GENERATE_CERTS_FILE} && bash gen_cert.sh 39 | #[ $? -eq 0 ] && echo "generate certs success" || exit 1 40 | #cd - 41 | #[ -d ${DEST_CERTS_DIR} ] || mkdir ${DEST_CERTS_DIR} 42 | #cp ${GENERATE_CERTS_FILE}/output/{ca.pem,ca-key.pem,kube-proxy-key.pem,kube-proxy.pem,kubelet-client-key.pem, \ 43 | #kubelet-client.pem} ${DEST_CERTS_DIR}/ 44 | 45 | # scp kubeconfig from master 46 | for master in `echo ${MASTER_HOSTS} | tr ',' ' '`;do 47 | scp -i ${DEPLOY_HOME_DIR}/private-key \ 48 | root@${master}:/home/kubernetes-operator/scripts/kubeconfig/output/kubelet-${LOCAL_IP}.kubeconfig \ 49 | ${DEST_CONFIG_DIR}/kubelet.kubeconfig 50 | [ $? -eq 0 ] && break 51 | done 52 | 53 | # generate kubeconfig 54 | #cp ${GENERATE_KUBECONFIG_FILE}/output/{kubelet.kubeconfig,bootstrap.kubeconfig} ${DEST_CONFIG_DIR}/ 55 | #sed -i -e "s#https://:6443#https://${MASTER_VIP}:6443#g" ${GENERATE_KUBECONFIG_FILE}/generate_node_kubeconfig.sh 56 | #cd ${GENERATE_KUBECONFIG_FILE} && bash generate_node_kubeconfig.sh 57 | #[ $? -eq 0 ] && echo "generate kubeconfig success" || exit 1 58 | #cp ${GENERATE_KUBECONFIG_FILE}/output/* ${DEST_CONFIG_DIR}/ 59 | #cd - 60 | 61 | # mkdir log dir 62 | [ -d ${KUBE_MASTER_LOG} ] || mkdir -pv ${KUBE_MASTER_LOG} 63 | 64 | # start service 65 | systemctl daemon-reload 66 | systemctl enable kubelet 67 | systemctl start kubelet 68 | systemctl status kubelet 69 | 70 | if [ $? -ne 0 ];then 71 | echo "deploy kubelet failed !!!" && exit 1 72 | fi 73 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package fake 20 | 21 | import ( 22 | clientset "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned" 23 | ecsv1 "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned/typed/ecs/v1" 24 | fakeecsv1 "github.com/gosoon/kubernetes-operator/pkg/client/clientset/versioned/typed/ecs/v1/fake" 25 | "k8s.io/apimachinery/pkg/runtime" 26 | "k8s.io/apimachinery/pkg/watch" 27 | "k8s.io/client-go/discovery" 28 | fakediscovery "k8s.io/client-go/discovery/fake" 29 | "k8s.io/client-go/testing" 30 | ) 31 | 32 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 33 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 34 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 35 | // for a real clientset and is mostly useful in simple unit tests. 36 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 37 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 38 | for _, obj := range objects { 39 | if err := o.Add(obj); err != nil { 40 | panic(err) 41 | } 42 | } 43 | 44 | cs := &Clientset{tracker: o} 45 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 46 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 47 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 48 | gvr := action.GetResource() 49 | ns := action.GetNamespace() 50 | watch, err := o.Watch(gvr, ns) 51 | if err != nil { 52 | return false, nil, err 53 | } 54 | return true, watch, nil 55 | }) 56 | 57 | return cs 58 | } 59 | 60 | // Clientset implements clientset.Interface. Meant to be embedded into a 61 | // struct to get a default implementation. This makes faking out just the method 62 | // you want to test easier. 63 | type Clientset struct { 64 | testing.Fake 65 | discovery *fakediscovery.FakeDiscovery 66 | tracker testing.ObjectTracker 67 | } 68 | 69 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 70 | return c.discovery 71 | } 72 | 73 | func (c *Clientset) Tracker() testing.ObjectTracker { 74 | return c.tracker 75 | } 76 | 77 | var _ clientset.Interface = &Clientset{} 78 | 79 | // EcsV1 retrieves the EcsV1Client 80 | func (c *Clientset) EcsV1() ecsv1.EcsV1Interface { 81 | return &fakeecsv1.FakeEcsV1{Fake: &c.Fake} 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kubernetes-operator 2 | 3 | [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) 4 | [![Go Report Card](https://goreportcard.com/badge/github.com/gosoon/kubernetes-operator)](https://goreportcard.com/report/github.com/gosoon/kubernetes-operator) 5 | 6 | kubernetes-operator is a control plane and manage all kubernetes cluster lifecycle. 7 | 8 | 9 | 10 | ## Introduce 11 | 12 | **kubernetes-operator contains several large parts**: 13 | 14 | - kubernetes-proxy: is a proxy and all requests pass through,look like a gateway. 15 | - kube-operator: is a kubernetes operator deploy in meta kubernetes and manage all kubernetes clusters(create、scale、delete). 16 | - cluster deploy: At present, the main focus is on kube-on-kube,and use ansible deploy kubernetes cluster and multiple kubernetes cluster applications, eg: metric-server、 promethus、log-polit、helm... 17 | - node-operator: Manage cluster upgrade, fault self-healing, etc. 18 | 19 | **The kubernetes-operator goal**: 20 | 21 | - kube-on-kube:Similar to Ant Financial kube-on-kube-operator. 22 | - kube-to-kube:The difference with `kube-on-kube` is that the master component of the business cluster is not in the meta cluster. 23 | - kube-to-cloud-kube : Manage clusters on multiple cloud environments. 24 | 25 | 26 | ## Getting started 27 | 28 | First you need to make two images,one is kubernetes-operator,the other one is ansibleinit。And deploy kubernetes-operator in your kubernetes-cluster,if you don't have a kubernetes cluster,please see `scripts/REAEME.md` and deploy one. 29 | 30 | ``` 31 | $ make images 32 | ``` 33 | 34 | ``` 35 | // update your image address and deploy kubernetes-operator 36 | $ kubectl create -f deploy/ 37 | namespace/ecs-system created 38 | customresourcedefinition.apiextensions.k8s.io/kubernetesclusters.ecs.yun.com created 39 | deployment.apps/kubernetes-operator created 40 | clusterrole.rbac.authorization.k8s.io/kubernetes-operator created 41 | clusterrolebinding.rbac.authorization.k8s.io/kubernetes-operator created 42 | serviceaccount/kubernetes-operator created 43 | 44 | 45 | // CustomResources is KubernetesCluster,"ecs" for short in the kubernetes-operator 46 | $ kubectl get crd 47 | NAME CREATED AT 48 | kubernetesclusters.ecs.yun.com 2019-08-05T12:23:52Z 49 | 50 | // update operator server in create_ecs.sh and create a cluster 51 | $ bash test/create_ecs.sh 52 | 53 | $ kubectl get ecs 54 | NAME STATUS AGE 55 | test-cluster Prechecking 45m 56 | ``` 57 | 58 | 59 | 60 | ## Development Plan 61 | 62 | 1. support deploy k3s、kubeedge cluster 63 | 2. support use kops deploy cluster 64 | 3. support for multiple version deploy 65 | 4. development node-operator 66 | 5. support admission control 67 | 68 | ## Detailed instructions 69 | 70 | - [kube-on-kube-operator 开发(一)](http://blog.tianfeiyu.com/2019/08/05/kube_on_kube_operator_1/) 71 | - [kube-on-kube-operator 开发(二)](http://blog.tianfeiyu.com/2019/08/07/kube_on_kube_operator_2/) 72 | - [kube-on-kube-operator 开发(三)](http://blog.tianfeiyu.com/2019/09/01/kube_on_kube_operator_3/) 73 | 74 | 75 | -------------------------------------------------------------------------------- /pkg/enum/task.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package enum 18 | 19 | import ecsv1 "github.com/gosoon/kubernetes-operator/pkg/apis/ecs/v1" 20 | 21 | const ( 22 | // Operation is operate annotation key 23 | Operation = "app.kubernetes.io/operation" 24 | 25 | // Spec is echo operate success and record the spec 26 | Spec = "app.kubernetes.io/spec" 27 | 28 | // state 29 | KubeCreating = string("creating") 30 | KubeCreateFailed = string("create-failed") 31 | KubeCreateFinished = string("create-finished") 32 | KubeScalingUp = string("scaling-up") 33 | KubeScaleUpFailed = string("scale-up-failed") 34 | KubeScaleUpFinished = string("scale-up-finished") 35 | KubeScalingDown = string("scaling-down") 36 | KubeScaleDownFailed = string("scale-down-failed") 37 | KubeScaleDownFinished = string("scale-down-finished") 38 | KubeTerminating = string("terminating") 39 | KubeTerminateFinished = string("terminate-finished") 40 | KubeTerminateFailed = string("terminate-failed") 41 | 42 | // TODO:to do it 43 | KubeUpdating = string("updating") 44 | KubeUpdateFailed = string("update-failed") 45 | KubeUpdateFinished = string("update-finished") 46 | KubeRollbacking = string("rollbacking") 47 | KubeRollbackFailed = string("rollback-failed") 48 | KubeRollbackFinished = string("rollback-finished") 49 | 50 | // phase 51 | New = ecsv1.KubernetesOperatorPhase("") 52 | Creating = ecsv1.KubernetesOperatorPhase("Creating") 53 | Prechecking = ecsv1.KubernetesOperatorPhase("Prechecking") 54 | Scaling = ecsv1.KubernetesOperatorPhase("Scaling") 55 | Running = ecsv1.KubernetesOperatorPhase("Running") 56 | Failed = ecsv1.KubernetesOperatorPhase("Failed") 57 | Terminating = ecsv1.KubernetesOperatorPhase("Terminating") 58 | 59 | // event message 60 | EcsSyncSuccess = string("ecs synced successfully") 61 | 62 | // event reason 63 | SyncedSuccess = string("Synced") 64 | 65 | // job events 66 | CreateKubeJobSuccess = string("CreateKubeJobSuccess") 67 | CreateKubeJobFailed = string("CreateKubeJobFailed") 68 | CreateScaleUpJobSuccess = string("CreateScaleUpJobSuccess") 69 | CreateScaleUpJobFailed = string("CreateScaleUpJobFailed") 70 | CreateScaleDownJobSuccess = string("CreateScaleDownJobSuccess") 71 | CreateScaleDownJobFailed = string("CreateScaleDownJobFailed") 72 | SetFinalizersSuccess = string("SetFinalizersSuccess") 73 | SetFinalizersFailed = string("SetFinalizersFailed") 74 | DeleteKubeJobSuccess = string("DeleteKubeJobSuccess") 75 | DeleteKubeJobFailed = string("DeleteKubeJobFailed") 76 | ) 77 | -------------------------------------------------------------------------------- /pkg/container/docker/exec.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 gosoon. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package docker 18 | 19 | import ( 20 | "io" 21 | 22 | "github.com/gosoon/kubernetes-operator/pkg/exec" 23 | ) 24 | 25 | // containerCmder implements exec.Cmder for docker containers 26 | type containerCmder struct { 27 | nameOrID string 28 | } 29 | 30 | // ContainerCmder creates a new exec.Cmder against a docker container 31 | func ContainerCmder(containerNameOrID string) exec.Cmder { 32 | return &containerCmder{ 33 | nameOrID: containerNameOrID, 34 | } 35 | } 36 | 37 | func (c *containerCmder) Command(command string, args ...string) exec.Cmd { 38 | return &containerCmd{ 39 | nameOrID: c.nameOrID, 40 | command: command, 41 | args: args, 42 | } 43 | } 44 | 45 | // containerCmd implements exec.Cmd for docker containers 46 | type containerCmd struct { 47 | nameOrID string // the container name or ID 48 | command string 49 | args []string 50 | env []string 51 | stdin io.Reader 52 | stdout io.Writer 53 | stderr io.Writer 54 | } 55 | 56 | func (c *containerCmd) Run() error { 57 | args := []string{ 58 | "exec", 59 | // run with privileges so we can remount etc.. 60 | // this might not make sense in the most general sense, but it is 61 | // important 62 | "--privileged", 63 | } 64 | if c.stdin != nil { 65 | args = append(args, 66 | "-i", // interactive so we can supply input 67 | ) 68 | } 69 | // set env 70 | for _, env := range c.env { 71 | args = append(args, "-e", env) 72 | } 73 | // specify the container and command, after this everything will be 74 | // args the command in the container rather than to docker 75 | args = append( 76 | args, 77 | c.nameOrID, // ... against the container 78 | c.command, // with the command specified 79 | ) 80 | args = append( 81 | args, 82 | // finally, with the caller args 83 | c.args..., 84 | ) 85 | cmd := exec.Command("docker", args...) 86 | if c.stdin != nil { 87 | cmd.SetStdin(c.stdin) 88 | } 89 | if c.stderr != nil { 90 | cmd.SetStderr(c.stderr) 91 | } 92 | if c.stdout != nil { 93 | cmd.SetStdout(c.stdout) 94 | } 95 | return cmd.Run() 96 | } 97 | 98 | func (c *containerCmd) SetEnv(env ...string) exec.Cmd { 99 | c.env = env 100 | return c 101 | } 102 | 103 | func (c *containerCmd) SetStdin(r io.Reader) exec.Cmd { 104 | c.stdin = r 105 | return c 106 | } 107 | 108 | func (c *containerCmd) SetStdout(w io.Writer) exec.Cmd { 109 | c.stdout = w 110 | return c 111 | } 112 | 113 | func (c *containerCmd) SetStderr(w io.Writer) exec.Cmd { 114 | c.stderr = w 115 | return c 116 | } 117 | -------------------------------------------------------------------------------- /scripts/deploy/deploy_etcd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | [ -e /etc/init.d/functions ] && . /etc/init.d/functions || exit 4 | [ -e ./config.sh ] && . ./config.sh || exit 5 | 6 | # etcd download releases doc: https://github.com/etcd-io/etcd/releases/ 7 | 8 | ETCD_BIN_DIR="../bin/${ETCD_VER}" 9 | CERTS_DIR="../certs/" 10 | ETCD_SYSTEMD_CONFIG_DIR="../systemd" 11 | ETCD_CONFIG_DIR="../config/etcd" 12 | GENERATE_CERTS_FILE="../certs/etcd" 13 | 14 | DEST_ETCD_CONFIG_DIR="/etc/etcd/etcd.conf" 15 | DEST_SYSTEMD_DIR="/usr/lib/systemd/system" 16 | DEST_CONFIG_DIR="/etc/etcd" 17 | DEST_CERTS_DIR="/etc/etcd/ssl" 18 | 19 | # TODO : if etcd not download and download etcd 20 | download_etcd(){ 21 | # choose either URL 22 | GOOGLE_URL=https://storage.googleapis.com/etcd 23 | GITHUB_URL=https://github.com/etcd-io/etcd/releases/download 24 | DOWNLOAD_URL=${GOOGLE_URL} 25 | 26 | rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz 27 | rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test 28 | 29 | curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz 30 | tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /tmp/etcd-download-test --strip-components=1 31 | rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz 32 | 33 | /tmp/etcd-download-test/etcd --version 34 | ETCDCTL_API=3 /tmp/etcd-download-test/etcdctl version 35 | } 36 | 37 | # cp etcd config 38 | cp ${ETCD_BIN_DIR}/{etcd,etcdctl} /usr/bin/ && chmod +x /usr/bin/{etcd,etcdctl} 39 | cp ${ETCD_SYSTEMD_CONFIG_DIR}/etcd.service ${DEST_SYSTEMD_DIR}/ 40 | [ -d ${DEST_CONFIG_DIR} ] || mkdir ${DEST_CONFIG_DIR} 41 | cp ${ETCD_CONFIG_DIR}/* ${DEST_CONFIG_DIR}/ 42 | 43 | # generate ssl 44 | cd ${GENERATE_CERTS_FILE} && bash gen_cert.sh 45 | [ $? -eq 0 ] && echo "generate certs success" || exit 1 46 | cd - 47 | 48 | # create ssl dir 49 | [ -d ${DEST_CERTS_DIR} ] || mkdir ${DEST_CERTS_DIR} 50 | cp ${GENERATE_CERTS_FILE}/output/* ${DEST_CERTS_DIR}/ 51 | 52 | # config etcd 53 | source ${ETCD_CONFIG_DIR}/* 54 | etcd_num=$(echo ${ETCD_HOSTS} | awk -F ',' '{print NF}') 55 | etcd_cluster="" 56 | for i in `seq 1 ${etcd_num}`;do 57 | ip=$(echo ${ETCD_HOSTS} | awk -v idx=$i -F ',' '{print $idx}') 58 | cluster=$(echo "node$i=https://${ip}:2380") 59 | if [ $i -ne ${etcd_num} ];then 60 | cluster="${cluster}," 61 | fi 62 | etcd_cluster="${etcd_cluster}${cluster}" 63 | if [ "X${ip}" == "X${LOCAL_IP}" ];then 64 | sed -i -e "s@\(ETCD_NAME=\).*@\1\"node${i}\"@g" ${DEST_CONFIG_DIR}/etcd.conf 65 | break 66 | fi 67 | done 68 | 69 | # replace ip addr 70 | sed -i -e "s@\(ETCD_INITIAL_ADVERTISE_PEER_URLS=\).*@\1\"https://${LOCAL_IP}:2380\"@g" ${DEST_CONFIG_DIR}/etcd.conf 71 | sed -i -e "s@\(ETCD_ADVERTISE_CLIENT_URLS=\).*@\1\"https://${LOCAL_IP}:2379\"@g" ${DEST_CONFIG_DIR}/etcd.conf 72 | sed -i -e "s@\(ETCD_INITIAL_CLUSTER=\).*@\1\"${etcd_cluster}\"@g" ${DEST_CONFIG_DIR}/etcd.conf 73 | 74 | useradd etcd 75 | [ -d ${ETCD_DATA_DIR} ] || mkdir -pv ${ETCD_DATA_DIR} 76 | chown -R etcd:etcd ${ETCD_DATA_DIR} 77 | 78 | # start etcd service 79 | systemctl daemon-reload 80 | systemctl enable etcd 81 | systemctl start etcd 82 | systemctl status etcd 83 | 84 | if [ $? -ne 0 ];then 85 | echo "deploy etcd failed !!!" && exit 1 86 | fi 87 | --------------------------------------------------------------------------------