Add support to install Kuryr as a network addon

Implements blueprint kubeadminstallable

Change-Id: I38cbc88ee7ee7b544ec15ee8f6ef9e0a0f474c2a
Co-Authored-By: Antoni Segura Puimedon <antonisp@celebdor.com>
Co-Authored-By: Michal Dulko <mdulko@redhat.com>
This commit is contained in:
vikaschoudhary16 2017-05-22 16:08:46 +05:30 committed by Michał Dulko
parent e2adbc70cc
commit 632d32be89
22 changed files with 594 additions and 0 deletions

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
.tox

4
.gitignore vendored
View File

@ -61,3 +61,7 @@ contrib/vagrant/user_local.conf
# Log files
*.log
# Binaries from docker images builds
kuryr-cni-bin
kuryr-cni

11
cni.Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM centos:7
LABEL authors="Antoni Segura Puimedon<toni@kuryr.org>, Vikas Choudhary<vichoudh@redhat.com>"
COPY . /opt/kuryr-kubernetes
COPY kuryr-cni /kuryr-cni
COPY kuryr-cni-bin /kuryr-cni-bin
COPY cni_ds_init /usr/bin/cni_ds_init
VOLUME [ "/sys/fs/cgroup" ]
ENTRYPOINT [ "cni_ds_init" ]

28
cni.spec Normal file
View File

@ -0,0 +1,28 @@
# -*- mode: python -*-
block_cipher = None
a = Analysis(['/usr/local/bin/kuryr-cni'],
pathex=['/usr/local/lib/python3.5/site-packages', '/usr/local/lib/python3.5/site-packages/eventlet/support'],
binaries=[],
datas=[],
hiddenimports=['backports.ssl_match_hostname', 'setuptools', 'kuryr_kubernetes.objects.vif', 'kuryr_kubernetes.os_vif_plug_noop', 'dns', 'vif_plug_ovs', 'vif_plug_linux_bridge', 'oslo_privsep'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='kuryr-cni',
debug=False,
strip=False,
upx=True,
console=True )

13
cni_builder Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash -ex
rm -f /opt/kuryr-kubernetes/kuryr-cni
rm -f /opt/kuryr-kubernetes/kuryr-cni-bin
pbr_version=$(find /usr/local/lib/python3.5/site-packages/ -type d \
-name 'kuryr_kubernetes*info' -exec basename {} \; \
| awk -F"-" '{sub(/\.dist/,"",$2); print $2}')
cat > /opt/kuryr-kubernetes/kuryr-cni << EOF
#!/bin/bash
export PBR_VERSION='$pbr_version'
/opt/cni/bin/kuryr-cni-bin
EOF
cp /dist/kuryr-cni /opt/kuryr-kubernetes/kuryr-cni-bin
chmod 744 /opt/kuryr-kubernetes/kuryr-cni

39
cni_builder.Dockerfile Normal file
View File

@ -0,0 +1,39 @@
FROM centos:centos6
LABEL authors="Antoni Segura Puimedon<toni@kuryr.org>, Vikas Choudhary<vichoudh@redhat.com>"
RUN yum install --setopt=tsflags=nodocs --assumeyes \
net-tools \
patch \
gcc \
python-devel \
wget \
openssl-devel \
zlib-devel \
git; \
yum clean all
ENV LANG en_US.UTF-8
RUN cd /usr/src \
&& wget https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tgz \
&& tar zxf Python-3.5.3.tgz \
&& cd Python-3.5.3 && ./configure --enable-shared && make altinstall \
&& ln -s /usr/local/lib/libpython3.5m.so.1.0 /usr/lib64/libpython3.5m.so.1.0
COPY . /opt/kuryr-kubernetes
# Installing from dev because of this issue, https://github.com/pyinstaller/pyinstaller/issues/2434
RUN cd /opt/kuryr-kubernetes \
&& patch -b kuryr_kubernetes/k8s_client.py < k8s_client.patch \
&& patch -b kuryr_kubernetes/cni/main.py < cni_main.patch \
&& pip3.5 install --no-cache-dir . \
&& pip3.5 install git+https://github.com/pyinstaller/pyinstaller.git \
&& pip3.5 install pyroute2 \
&& sed -i -e "s/self.bytebuffer + newdata/self.bytebuffer + newdata.encode()/" /usr/local/lib/python3.5/codecs.py
COPY cni_builder /usr/bin/cni_builder
COPY hooks/* /usr/local/lib/python3.5/site-packages/PyInstaller/hooks/
COPY cni.spec /
RUN pyinstaller cni.spec
CMD ["cni_builder"]
ENTRYPOINT [ "/bin/bash" ]

16
cni_ds_init Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash -e
rm -f /etc/cni/net.d/10-kuryr.conf
rm -f /etc/cni/net.d/99-loopback.conf
rm -f /opt/cni/bin/kuryr-cni
rm -f /opt/cni/bin/kuryr-cni-bin
rm -rf /etc/kuryr
mkdir /etc/kuryr
cp /var/run/secrets/kubernetes.io/serviceaccount/token /etc/kuryr/token
cp /var/run/secrets/kubernetes.io/serviceaccount/ca.crt /etc/kuryr/ca.crt
cp /opt/kuryr-kubernetes/etc/cni/net.d/* /etc/cni/net.d/
cp /kuryr-cni-bin /opt/cni/bin/kuryr-cni-bin
cp /kuryr-cni /opt/cni/bin/kuryr-cni
cat /tmp/kuryr/* > /etc/kuryr/kuryr.conf
while true; do sleep 3600; done

12
cni_main.patch Normal file
View File

@ -0,0 +1,12 @@
--- /root/tmp/kuryr-kubernetes/kuryr_kubernetes/cni/main.py 2017-06-19 07:15:39.898398766 -0400
+++ kuryr_kubernetes/cni/main.py 2017-06-22 04:28:41.421123949 -0400
@@ -61,6 +61,9 @@
config.init(args)
config.setup_logging()
os_vif.initialize()
+ ovs = os_vif._EXT_MANAGER['ovs'].obj
+ ovs_mod = sys.modules[ovs.__module__]
+ ovs_mod.linux_net.privsep.vif_plug.start(ovs_mod.linux_net.privsep.priv_context.Method.FORK)
clients.setup_kubernetes_client()
self._pipeline = h_cni.CNIPipeline()
self._watcher = k_watcher.Watcher(self._pipeline)

23
controller.Dockerfile Normal file
View File

@ -0,0 +1,23 @@
FROM centos:7
LABEL authors="Antoni Segura Puimedon<toni@kuryr.org>, Vikas Choudhary<vichoudh@redhat.com>"
COPY . /opt/kuryr-kubernetes
RUN yum install -y epel-release \
&& yum install -y --setopt=tsflags=nodocs python-pip \
&& yum install --setopt=tsflags=nodocs --assumeyes inet-tools gcc python-devel wget git \
&& cd /opt/kuryr-kubernetes \
&& pip install --no-cache-dir . \
&& rm -fr .git \
&& yum -y history undo last \
&& groupadd -r kuryr -g 711 \
&& useradd -u 711 -g kuryr \
-d /opt/kuryr-kubernetes \
-s /sbin/nologin \
-c "Kuryr controller user" \
kuryr \
&& chown kuryr:kuryr /opt/kuryr-kubernetes
USER kuryr
CMD ["--config-dir", "/etc/kuryr"]
ENTRYPOINT [ "/usr/bin/kuryr-k8s-controller" ]

View File

@ -281,3 +281,185 @@ spec:
EOF
fi
}
function indent() {
sed 's/^/ /';
}
function generate_kuryr_configmap() {
local output_dir
local controller_conf_path
local cni_conf_path
output_dir=$1
controller_conf_path=${2:-""}
cni_conf_path=${3:-$controller_conf_path}
mkdir -p "$output_dir"
rm -f ${output_dir}/config_map.yml
# kuryr-contoller config
cat >> "${output_dir}/config_map.yml" << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: kuryr-config
namespace: kube-system
data:
kuryr.conf: |
EOF
cat $controller_conf_path | indent >> "${output_dir}/config_map.yml"
# kuryr-cni config (different token_file location)
# token_file = /etc/kuryr/token
# ssl_ca_crt_file = /etc/kuryr/ca.crt
# ssl_verify_server_crt = true
cat >> "${output_dir}/config_map.yml" << EOF
kuryr-cni.conf: |
EOF
cat $cni_conf_path | indent >> "${output_dir}/config_map.yml"
}
function generate_kuryr_service_account() {
output_dir=$1
mkdir -p "$output_dir"
rm -f ${output_dir}/service_account.yml
cat >> "${output_dir}/service_account.yml" << EOF
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kuryr-controller
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: kuryr-controller
rules:
- apiGroups:
- ""
verbs: ["*"]
resources:
- deployments
- endpoints
- ingress
- pods
- policies
- nodes
- services
- services/status
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: kuryr-controller-global
subjects:
- kind: ServiceAccount
name: kuryr-controller
namespace: kube-system
roleRef:
kind: ClusterRole
name: kuryr-controller
apiGroup: rbac.authorization.k8s.io
EOF
}
function generate_controller_deployment() {
output_dir=$1
mkdir -p "$output_dir"
rm -f ${output_dir}/controller_deployment.yml
cat >> "${output_dir}/controller_deployment.yml" << EOF
apiVersion: apps/v1beta1
kind: Deployment
metadata:
labels:
name: kuryr-controller
name: kuryr-controller
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
name: kuryr-controller
name: kuryr-controller
spec:
serviceAccountName: kuryr-controller
automountServiceAccountToken: true
hostNetwork: true
containers:
- image: kuryr/controller:latest
imagePullPolicy: Never
name: controller
terminationMessagePath: "/dev/termination-log"
volumeMounts:
- name: config-volume
mountPath: "/etc/kuryr/kuryr.conf"
subPath: kuryr.conf
volumes:
- name: config-volume
configMap:
name: kuryr-config
restartPolicy: Always
EOF
}
function generate_cni_daemon_set() {
output_dir=$1
mkdir -p "$output_dir"
rm -f ${output_dir}/cni_ds.yml
cat >> "${output_dir}/cni_ds.yml" << EOF
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: kuryr-cni-ds
namespace: kube-system
labels:
tier: node
app: kuryr
spec:
template:
metadata:
labels:
tier: node
app: kuryr
spec:
hostNetwork: true
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
serviceAccountName: kuryr-controller
containers:
- name: kuryr-cni
image: kuryr/cni:latest
imagePullPolicy: Never
command: [ "cni_ds_init" ]
securityContext:
privileged: true
volumeMounts:
- name: bin
mountPath: /opt/cni/bin
- name: net-conf
mountPath: /etc/cni/net.d
- name: config-volume
mountPath: /tmp/kuryr/kuryr.conf
subPath: kuryr-cni.conf
- name: etc
mountPath: /etc
volumes:
- name: bin
hostPath:
path: /opt/cni/bin
- name: net-conf
hostPath:
path: /etc/cni/net.d
- name: config-volume
configMap:
name: kuryr-config
- name: etc
hostPath:
path: /etc
EOF
}

View File

@ -0,0 +1,90 @@
Kuryr installation as a Kubernetes network addon
================================================
Building images
~~~~~~~~~~~~~~~
First you should build kuryr-controller and kuryr-cni docker images and place
them on cluster-wide accessible registry.
For creating controller image on local machine: ::
$ docker build -t kuryr/controller -f controller.Dockerfile .
For creating cni daemonset image on local machine: ::
$ ./tools/build_cni_daemonset_image
Alternatively, you can remove ``imagePullPolicy: Never`` from kuryr-controller
Deployment and kuryr-cni DaemonSet definitions to use pre-built
`controller <https://hub.docker.com/r/kuryr/controller/>`_ and `cni <https://hub.docker.com/r/kuryr/cni/>`_
images from the Docker Hub. Those definitions will be generated in next step.
Generating Kuryr resource definitions for Kubernetes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
kuryr-kubernetes includes a tool that lets you generate resource definitions
that can be used to Deploy Kuryr on Kubernetes. The script is placed in
``tools/generate_k8s_resource_definitions.sh`` and takes up to 3 arguments: ::
$ ./tools/generate_k8s_resource_definitions <output_dir> [<controller_conf_path>] [<cni_conf_path>]
* ``output_dir`` - directory where to put yaml files with definitions.
* ``controller_conf_path`` - path to custom kuryr-controller configuration file.
* ``cni_conf_path`` - path to custom kuryr-cni configuration file (defaults to
``controller_conf_path``).
If no path to config files is provided, script automatically generates minimal
configuration. However some of the options should be filled by the user. You can
do that either by editing the file after the ConfigMap definition is generated
or provide your options as environment variables before running the script.
Below is the list of available variables:
* ``$KURYR_K8S_API_ROOT`` - ``[kubernetes]api_root`` (default: https://127.0.0.1:6443)
* ``$KURYR_K8S_AUTH_URL`` - ``[neutron]auth_url`` (default: http://127.0.0.1/identity)
* ``$KURYR_K8S_USERNAME`` - ``[neutron]username`` (default: admin)
* ``$KURYR_K8S_PASSWORD`` - ``[neutron]password`` (default: password)
* ``$KURYR_K8S_USER_DOMAIN_NAME`` - ``[neutron]user_domain_name`` (default: Default)
* ``$KURYR_K8S_KURYR_PROJECT_ID`` - ``[neutron]kuryr_project_id``
* ``$KURYR_K8S_PROJECT_DOMAIN_NAME`` - ``[neutron]project_domain_name`` (default: Default)
* ``$KURYR_K8S_PROJECT_ID`` - ``[neutron]k8s_project_id``
* ``$KURYR_K8S_POD_SUBNET_ID`` - ``[neutron_defaults]pod_subnet_id``
* ``$KURYR_K8S_POD_SG`` - ``[neutron_defaults]pod_sg``
* ``$KURYR_K8S_SERVICE_SUBNET_ID`` - ``[neutron_defaults]service_subnet_id``
* ``$KURYR_K8S_WORKER_NODES_SUBNET`` - ``[pod_vif_nested]worker_nodes_subnet``
* ``$KURYR_K8S_BINDING_DRIVER`` - ``[binding]driver`` (default: ``kuryr.lib.binding.drivers.vlan``)
* ``$KURYR_K8S_BINDING_IFACE`` - ``[binding]link_iface`` (default: eth0)
Example run: ::
$ KURYR_K8S_API_ROOT="192.168.0.1:6443" ./tools/generate_k8s_resource_definitions /tmp
This should generate 4 files in your ``<output_dir>``:
* config_map.yml
* service_account.yml
* controller_deployment.yml
* cni_ds.yml
Deploying Kuryr resources on Kubernetes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To deploy the files on your Kubernetes cluster run: ::
$ kubectl apply -f config_map.yml -n kube-system
$ kubectl apply -f service_account.yml -n kube-system
$ kubectl apply -f conteoller_deployment.yml -n kube-system
$ kubectl apply -f cni_ds.yml -n kube-system
After successful completion:
* kuryr-controller Deployment object, with single replica count, will get
created in default namespace.
* kuryr-cni gets installed as a daemonset object on all the nodes in kube-system
namespace
To see kuryr-controller logs ::
$ kubectl logs <pod-name>
NOTE: kuryr-cni has no logs and to debug failures you need to check out kubelet
logs.

View File

@ -38,3 +38,4 @@ This section describes how you can install and configure kuryr-kubernetes
trunk_ports
testing_connectivity
testing_nested_connectivity
containerized

View File

@ -0,0 +1,15 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from PyInstaller.utils.hooks import collect_submodules
hiddenimports = collect_submodules('backports')

2
hooks/hook-dns.py Normal file
View File

@ -0,0 +1,2 @@
from PyInstaller.utils.hooks import collect_submodules
hiddenimports = collect_submodules('dns')

View File

@ -0,0 +1,9 @@
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
from PyInstaller.utils.hooks import copy_metadata
datas = copy_metadata('kuryr_kubernetes')
datas += collect_data_files('kuryr_kubernetes')
hiddenimports = collect_submodules('kuryr_kubernetes.cni.binding')

7
hooks/hook-os_vif.py Normal file
View File

@ -0,0 +1,7 @@
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
from PyInstaller.utils.hooks import copy_metadata
datas = copy_metadata('os_vif')
datas += collect_data_files('os_vif')
hiddenimports = collect_submodules('os_vif.objects')

7
hooks/hook-pyroute2.py Normal file
View File

@ -0,0 +1,7 @@
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import collect_submodules
from PyInstaller.utils.hooks import copy_metadata
datas = copy_metadata('pyroute2')
datas += collect_data_files('pyroute2')
hiddenimports = collect_submodules('pyroute2')

View File

@ -0,0 +1,2 @@
from PyInstaller.utils.hooks import collect_submodules
hiddenimports = collect_submodules('vif_plug_linux_bridge')

View File

@ -0,0 +1,2 @@
from PyInstaller.utils.hooks import collect_submodules
hiddenimports = collect_submodules('vif_plug_ovs')

11
k8s_client.patch Normal file
View File

@ -0,0 +1,11 @@
--- /root/tmp/kuryr-kubernetes/kuryr_kubernetes/k8s_client.py 2017-06-19 07:15:39.901398831 -0400
+++ kuryr_kubernetes/k8s_client.py 2017-06-22 06:14:48.177325667 -0400
@@ -138,7 +138,7 @@
headers=header)) as response:
if not response.ok:
raise exc.K8sClientException(response.text)
- for line in response.iter_lines(delimiter='\n'):
+ for line in response.iter_lines(delimiter=b'\n'):
line = line.strip()
if line:
yield jsonutils.loads(line)

14
tools/build_cni_daemonset_image Executable file
View File

@ -0,0 +1,14 @@
#!/bin/bash -ex
BUILDER_TAG="kuryr/cni-builder"
CNI_TAG="kuryr/cni"
# build the cni image
docker build -t "$BUILDER_TAG" -f cni_builder.Dockerfile .
docker run \
--rm \
-v $(pwd):/opt/kuryr-kubernetes \
"$BUILDER_TAG":latest
# create cni daemonset image
docker build -t "$CNI_TAG" -f cni.Dockerfile .

View File

@ -0,0 +1,105 @@
#!/bin/bash
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
set -e
DIR=$( cd "$( dirname "$0" )" && pwd )
source "$DIR/../devstack/lib/kuryr_kubernetes"
OUTPUT_DIR=${1:-.}
CONTROLLER_CONF_PATH=${2:-""}
CNI_CONF_PATH=${3:-$CONTROLLER_CONF_PATH}
if [ -z $CONTROLLER_CONF_PATH ]; then
api_root=${KURYR_K8S_API_ROOT:-https://127.0.0.1:6443}
auth_url=${KURYR_K8S_AUTH_URL:-http://127.0.0.1/identity}
username=${KURYR_K8S_USERNAME:-admin}
password=${KURYR_K8S_PASSWORD:-password}
user_domain_name=${KURYR_K8S_USER_DOMAIN_NAME:-Default}
kuryr_project_id=${KURYR_K8S_KURYR_PROJECT_ID}
project_domain_name=${KURYR_K8S_PROJECT_DOMAIN_NAME:-Default}
k8s_project_id=${KURYR_K8S_PROJECT_ID}
pod_subnet_id=${KURYR_K8S_POD_SUBNET_ID}
pod_sg=${KURYR_K8S_POD_SG}
service_subnet_id=${KURYR_K8S_SERVICE_SUBNET_ID}
worker_nodes_subnet=${KURYR_K8S_WORKER_NODES_SUBNET}
binding_driver=${KURYR_K8S_BINDING_DRIVER:-kuryr.lib.binding.drivers.vlan}
binding_iface=${KURYR_K8S_BINDING_IFACE:-eth0}
CONTROLLER_CONF_PATH="${OUTPUT_DIR}/kuryr.conf"
rm -f $CONTROLLER_CONF_PATH
cat >> $CONTROLLER_CONF_PATH << EOF
[DEFAULT]
debug = true
[kubernetes]
api_root = $api_root
token_file = /var/run/secrets/kubernetes.io/serviceaccount/token
ssl_ca_crt_file = /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
[neutron]
signing_dir = /var/cache/kuryr
project_domain_name = $project_domain_name
project_id = $kuryr_project_id
user_domain_name = $user_domain_name
username = $username
password = $password
auth_url = $auth_url
auth_type = password
[neutron_defaults]
ovs_bridge = br-int
service_subnet = $service_subnet_id
pod_security_groups = $pod_sg
pod_subnet = $pod_subnet_id
project = $k8s_project_id
EOF
if [ ! -z $binding_driver ]; then
cat >> $CONTROLLER_CONF_PATH << EOF
[pod_vif_nested]
worker_nodes_subnet = $worker_nodes_subnet
[binding]
driver = $binding_driver
link_iface = $binding_iface
EOF
fi
fi
if [ -z $CNI_CONF_PATH ]; then
CNI_CONF_PATH="${OUTPUT_DIR}/kuryr-cni.conf"
rm -f $CNI_CONF_PATH
cat >> $CNI_CONF_PATH << EOF
[DEFAULT]
debug = true
use_stderr = true
[kubernetes]
api_root = $api_root
token_file = /etc/kuryr/token
ssl_ca_crt_file = /etc/kuryr/ca.crt
ssl_verify_server_crt = true
EOF
if [ ! -z $binding_driver ]; then
cat >> $CNI_CONF_PATH << EOF
[pod_vif_nested]
worker_nodes_subnet = $worker_nodes_subnet
[binding]
driver = $binding_driver
link_iface = $binding_iface
EOF
fi
fi
generate_kuryr_configmap $OUTPUT_DIR $CONTROLLER_CONF_PATH $CNI_CONF_PATH
generate_kuryr_service_account $OUTPUT_DIR
generate_controller_deployment $OUTPUT_DIR
generate_cni_daemon_set $OUTPUT_DIR