From e0de6af3ecb68e9a80bdb9e666aaecacf7d79753 Mon Sep 17 00:00:00 2001 From: Daneyon Hansen <danehans@cisco.com> Date: Mon, 16 Feb 2015 21:37:03 +0000 Subject: [PATCH] Implements: blueprint heat-template Previously, the kolla heat template was maintained outside of the project in the larsks/heat-kubernetes repo. This patch adds the templates to the project's devenv directory. Additionally, the patch updates the templates and documentation to reflect the design changes outlined in the following spec: https://github.com/stackforge/kolla/blob/master/specs/containerize-openstack.rst Change-Id: I11305f87cceb2495478d458a7e381d20838e664a --- README.md | 216 +++++++++----------------------------- devenv/README.md | 143 +++++++++++++++++++++++++ devenv/kollacluster.yaml | 109 +++++++++++++++++++ devenv/kollanet.png | Bin 0 -> 26014 bytes devenv/kollanode.yaml | 199 +++++++++++++++++++++++++++++++++++ devenv/local.yaml.example | 3 + 6 files changed, 502 insertions(+), 168 deletions(-) create mode 100644 devenv/README.md create mode 100644 devenv/kollacluster.yaml create mode 100644 devenv/kollanet.png create mode 100644 devenv/kollanode.yaml create mode 100644 devenv/local.yaml.example diff --git a/README.md b/README.md index caaf6803c1..354656d08e 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,36 @@ -Kolla -===== +Kolla Overview +============== -The Kolla project is part of the OpenStack TripleO effort, focused on -deploying OpenStack environments using [Kubernetes][] and [Docker][] -containers. +The Kolla project is part of the OpenStack [TripleO][] effort, focused +on deploying OpenStack services using [Docker][] containers. The initial +system [spec][] provides additional details of Kolla and the use cases +it addresses. -[kubernetes]: https://github.com/GoogleCloudPlatform/kubernetes -[docker]: http://docker.com/ +[TripleO]: https://wiki.openstack.org/wiki/TripleO +[Docker]: http://docker.com/ +[spec]: https://github.com/stackforge/kolla/blob/master/specs/containerize-openstack.rst Getting Started =============== -Kubernetes deployment on bare metal is a complex topic which is beyond the -scope of this project at this time. The developers require a development test -environment. As a result, one of the developers has created a Heat based -deployment tool that can be -found [here](https://github.com/larsks/heat-kubernetes). +Deployment on bare metal is a complex topic which is beyond the scope of +the project at this time. An environment to simplify the deployment of a +single or multi-node Kolla cluster is required for development purposes. +As a result, a [Heat template][] has been created for deploying a Kolla +cluster to an existing OpenStack cloud. +[Heat template]: (https://github.com/stackforge/kolla/blob/master/devenv/README.md) -Build Docker Images -------------------- +Docker Images +------------- -Images are built by the Kolla project maintainers. It is possible to build -unique images with specific changes, but these would end up in a personal -namespace. Read the docs directory image workflow documentation for more -details. +The [Docker images][] are built by the Kolla project maintainers. A detailed +process for contributing to the images can be found [here][]. Images reside +in the Docker Hub [Kollaglue repo][]. + +[here]: https://github.com/stackforge/kolla/blob/master/docs/image-building.md +[Docker images]: https://docs.docker.com/userguide/dockerimages/ +[Kollaglue repo]: https://registry.hub.docker.com/repos/kollaglue/ The Kolla developers build images in the kollaglue namespace for the following services: @@ -45,161 +51,35 @@ $ sudo docker search kollaglue ``` A list of the upstream built docker images will be shown. -Use Kubernetes to Deploy OpenStack ----------------------------------- - -At this point, we believe the key features for a minimum viable feature set -are implemented. This includes the capability to launch virtual machines in -Nova. One key fact is that networking may not entirely work properly yet -until Neutron is finished, so the virtual machines may not actually behave -as expected for an end user deployment. - -Two options exist for those without an existing Kubernetes environment: - -The upstream Kubernetes community provides instructions for running Kubernetes -using Vagrant, available from: -https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/getting-started-guides/vagrant.md - -The Kolla developers develop Kolla in OpenStack, using Heat to provision the -necessary servers and other resources. If you are familiar with Heat and -have a correctly configured environment available, this allows deployment -of a working Kubernetes cluster automatically. The Heat templates are -available from https://github.com/larsks/heat-kubernetes/. The templates -require at least Heat 2014.1.3 (earlier versions have a bug that will prevent -the templates from working). - -Here are some simple steps to get things rolling using the Heat templates: - -1. Clone the repository: - ``` - git clone https://github.com/larsks/heat-kubernetes/ - cd heat-kubernetes - ``` - -2. Create an appropriate image by running the get_image.sh script in this - repository. This will generate an image called `fedora-20-k8s.qcow2`. - Upload this image to Glance. You can also obtain an appropriate image from - https://fedorapeople.org/groups/heat/kolla/fedora-20-k8s.qcow2 - -3. Create a file `local.yaml` with settings appropriate to your OpenStack - environment. It should look something like: - ``` - parameters: - server_image: fedora-20-k8s - ssh_key_name: sdake - - - dns_nameserver: 8.8.8.8 - external_network_id: 6e7e7701-46a0-49c0-9f06-ac5abc79d6ae - number_of_minions: 1 - server_flavor: m1.large - ``` - You *must* provide settings for external_network_id and ssh_key_name; these - are local to your environment. You will probably also need to provide - a value for server_image, which should be the name (or UUID) of a Fedora 20 - cloud image or derivative. - -4. `heat stack-create -f kubecluster.yaml -e local.yaml my-kube-cluster` - -5. Determine the ip addresses of your cluster hosts by running: - ``` - heat output-show my-kube-cluster kube_minions_external - ``` - -6. Connect to the minion node with `ssh fedora@${minion-ip}` - -7. On the minion node: - ``` - minion$ git clone http://github.com/stackforge/kolla - minion$ cd kolla - minion$ ./tools/start - ``` - -Debugging -========== -A few commands for debugging the system. - -``` -$ sudo docker images -``` -Lists all images that have been pulled from the upstream kollaglue repository -thus far. This can be run on the minion during the `./start` operation to -check on the download progress. - - -``` -$ sudo docker ps -a -``` -This will show all processes that docker has started. Removing the `-a` will -show only active processes. This can be run on the minion during the `./start` -operation to check that the containers are orchestrated. - - -``` -$ sudo docker logs <containerid> -``` -This shows the logging output of each service in a container. The containerid -can be obtained via the `docker ps` operation. This can be run on the minion -during the `./start` operation to debug the container. - -``` -$ kubectl get pods -``` -This lists all pods of which Kubernetes is aware. This can be run on the -master or minion. - -``` -$ sudo systemctl restart kube-apiserver -$ sudo systemctl restart kube-scheduler -``` -This command is needed on the master after heat finishes the creation of the -Kubernetes system (ie: my-kube-cluster is in CREATE_COMPLETE state). This is -just a workaround for a bug in kubernetes that should be fixed soon. - - -``` -$ journalctl -f -l -xn -u kube-apiserver -u etcd -u kube-scheduler -``` -This shows log output on the server for the various daemons and can be filed -in bug reports in the upstream launchpad tracker. +Directories +=========== -``` -$ journalctl -f -l -xn -u kubelet.service -u kube-proxy -u docker -``` -This shows log output on the minion for the various daemons and can be filed -in bug reports in the upstream launchpad tracker. +* docker - contains artifacts for use with docker build to build appropriate + images +* k8s - contains service and pod configuration information for Kubernetes +* tools - contains different tools for interacting with Kolla +* devenv - A collection of tools and resources for managing a Kolla + development environment. -``` -$ telnet minion_ip 3306 -``` -This shows that the Mariadb service is running on the minions. Output should -appear as follows +Getting Involved +================ -``` -$ telnet 10.0.0.4 3306 -Trying 10.0.0.4... -Connected to 10.0.0.4. -Escape character is '^]'. +Need a feature? Find a bug? Let us know! Contributions are much appreciated +and should follow the standard [Gerrit workflow][]. -5.5.39-MariaDB-wsrep -``` +- We communicate using the #tripleo irc channel. +- File bugs, blueprints, track releases, etc on [Launchpad][]. +- Attend weekly [meetings][]. +- Contribute [code][] -If the connection closes before mysql responds then the proxy is not properly -connecting to the database. This can be seen by using jounalctl and watching -for a connection error on the node that you can't connect to mysql through. +[Gerrit workflow]: https://wiki.openstack.org/wiki/Gerrit_Workflow +[Launchpad]: https://launchpad.net/kolla +[meetings]: https://wiki.openstack.org/wiki/Meetings/Kolla +[code]: https://github.com/stackforge/kolla -``` -$ journalctl -f -l -xn -u kube-proxy -``` -If you can conect though one and not the other there's probably a problem with -the overlay network. Double check that you're tunning kernel 3.16+ because -vxlan support is required. If you kernel version is good try restarting -openvswitch on both nodes. This has usually fixed the connection issues. +Contributors +============ -Directories -=========== +Check out who's [contributing][]. -* docker - contains artifacts for use with docker build to build appropriate - images -* k8s - contains service and pod configuration information for Kubernetes -* tools - contains different tools for interacting with Kolla +[contributing]: https://github.com/stackforge/kolla/graphs/contributors diff --git a/devenv/README.md b/devenv/README.md new file mode 100644 index 0000000000..406b60e427 --- /dev/null +++ b/devenv/README.md @@ -0,0 +1,143 @@ +A Kolla Cluster with Heat +========================= + +These [Heat][] templates will deploy an *N*-node [Kolla][] cluster, +where *N* is the value of the `number_of_nodes` parameter you +specify when creating the stack. + +Kolla has recently undergone a considerable design change. The details +of the design change is addressed in this [spec][]. As part of the +design change, containers share pid and networking namespaces with +the Docker host. Therefore, containers no longer connect to a docker0 +bridge and have separate networking from the host. As a result, Kolla +networking has a configuration similar to: + + + +Sharing pid and networking namespaces is detailed in the +[super privileged containers][] concept. + +The Kolla cluster is based on Fedora 21, and makes use of the +[pkilambi/docker][] [COPR][] repository for Docker packages. This +is because Kolla requires a newer version of Docker not currently +packaged in Fedora 21. + +These templates are designed to work with the Icehouse or Juno +versions of Heat. If using Icehouse Heat, this [patch][] is +required to correct a bug with template validation when using the +"Fn::Join" function). + +[heat]: https://wiki.openstack.org/wiki/Heat +[kolla]: https://launchpad.net/kolla +[pkilambi/docker]: https://copr.fedoraproject.org/coprs/pkilambi/docker +[copr]: https://copr.fedoraproject.org/ +[spec]: https://review.openstack.org/#/c/153798/ +[super privileged containers]: http://sdake.io/2015/01/28/an-atomic-upgrade-process-for-openstack-compute-nodes/ +[patch]: https://review.openstack.org/#/c/121139/ + +Create the Glance Image +======================= + +After cloning the project, run the get-image.sh script from the project's +devenv directory: + + $ ./get-image.sh + +The script will create a Fedora 21 image with the required modifications. + +Copy the image to your Glance image store: + + $ glance image-create --name "fedora-21-x86_64" \ + --file /var/lib/libvirt/images/fedora-21-x86_64 \ + --disk-format qcow2 --container-format bare \ + --is-public True --progress + +Create the Stack +================ + +Copy local.yaml.example to local.yaml and edit the contents to match +your deployment environment. Here is an example of a customized +local.yaml: + + parameters: + ssh_key_name: admin-key + external_network_id: 028d70dd-67b8-4901-8bdd-0c62b06cce2d + dns_nameserver: 192.168.200.1 + +Review the parameters section of kollacluster.yaml for a full list of +configuration options. **Note:** You must provide values for: + +- `ssh_key_name` +- `external_network_id` + +And then create the stack, referencing that environment file: + + $ heat stack-create -f kollacluster.yaml -e local.yaml kolla-cluster + +Access the Kolla Nodes +====================== + +You can get the ip address of the Kolla nodes using the `heat +output-show` command: + + $ heat output-show kolla-cluster kolla_node_external_ip + "192.168.200.86" + +You can ssh into that server as the `fedora` user: + + $ ssh fedora@192.168.200.86 + +And once logged in you can run Docker commands, etc: + + $ sudo docker images + +Debugging +========== +A few commands for debugging the system. + +``` +$ sudo docker images +``` +Lists all images that have been pulled from the upstream kollaglue repository +thus far. This can be run on the node during the `./start` operation to +check on the download progress. + +``` +$ sudo docker ps -a +``` +This will show all processes that docker has started. Removing the `-a` will +show only active processes. This can be run on the node during the `./start` +operation to check that the containers are orchestrated. + +``` +$ sudo docker logs <containerid> +``` +This shows the logging output of each service in a container. The containerid +can be obtained via the `docker ps` operation. This can be run on the node +during the `./start` operation to debug the container. + +``` +$ sudo systemctl restart docker +``` +Restarts the Docker service on the node. + +``` +$ journalctl -f -l -xn -u docker +``` +This shows log output on the server for the docker daemon and can be filed +in bug reports in the upstream launchpad tracker. + +``` +$ telnet <NODE_IP> 3306 +``` +You can use telnet to test connectivity to a container. This example demonstrates +the Mariadb service is running on the node. Output should appear as follows + +``` +$ telnet 10.0.0.4 3306 +Trying 10.0.0.4... +Connected to 10.0.0.4. +Escape character is '^]'. + +5.5.39-MariaDB-wsrep +``` diff --git a/devenv/kollacluster.yaml b/devenv/kollacluster.yaml new file mode 100644 index 0000000000..0c8c65a956 --- /dev/null +++ b/devenv/kollacluster.yaml @@ -0,0 +1,109 @@ +heat_template_version: 2013-05-23 + +description: > + This template will boot a Kolla cluster with one or more + nodes (as specified by the number_of_nodes parameter, + which defaults to "1"). + +parameters: + # + # REQUIRED PARAMETERS + # + ssh_key_name: + type: string + description: name of ssh key to be provisioned on the Nova instances + + external_network_id: + type: string + description: uuid of a network to use for floating ip addresses + # + # OPTIONAL PARAMETERS + # + server_image: + type: string + default: fedora-21-x86_64 + description: glance image used to boot the Nova instance + + server_flavor: + type: string + default: m1.small + description: flavor to use when booting the Nova instance + + dns_nameserver: + type: string + description: address of a dns nameserver reachable in your environment + default: 8.8.8.8 + + number_of_nodes: + type: string + description: how many kolla nodes to spawn + default: 1 + + fixed_network_cidr: + type: string + description: network range for fixed ip network + default: 10.0.0.0/24 + +resources: + + ###################################################################### + # + # network resources. allocate a network and router for our server. + # it would also be possible to take advantage of existing network + # resources (and have the deployer provide network and subnet ids, + # etc, as parameters), but I wanted to minmize the amount of + # configuration necessary to make this go. + fixed_network: + type: "OS::Neutron::Net" + + # This is the subnet on which we will deploy our server eth0. + fixed_subnet: + type: "OS::Neutron::Subnet" + properties: + cidr: {get_param: fixed_network_cidr} + network_id: + get_resource: fixed_network + dns_nameservers: + - get_param: dns_nameserver + + # create a router attached to the external network provided as a + # parameter to this stack. + extrouter: + type: "OS::Neutron::Router" + properties: + external_gateway_info: + network: + get_param: external_network_id + + # attached fixed_subnet to our extrouter router. + extrouter_inside: + type: "OS::Neutron::RouterInterface" + properties: + router_id: + get_resource: extrouter + subnet_id: + get_resource: + fixed_subnet + + kolla_nodes: + type: "OS::Heat::ResourceGroup" + depends_on: + - extrouter_inside + properties: + count: {get_param: number_of_nodes} + resource_def: + type: kollanode.yaml + properties: + ssh_key_name: {get_param: ssh_key_name} + server_image: {get_param: server_image} + server_flavor: {get_param: server_flavor} + fixed_network_id: {get_resource: fixed_network} + fixed_subnet_id: {get_resource: fixed_subnet} + external_network_id: {get_param: external_network_id} +outputs: + + kolla_node_internal_ip: + value: {get_attr: [kolla_nodes, kolla_node_ip_eth0]} + + kolla_node_external_ip: + value: {get_attr: [kolla_nodes, kolla_node_external_ip]} diff --git a/devenv/kollanet.png b/devenv/kollanet.png new file mode 100644 index 0000000000000000000000000000000000000000..cfb0c60140b25710a2979f2e3c6a98f41449752e GIT binary patch literal 26014 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 literal 0 HcmV?d00001 diff --git a/devenv/kollanode.yaml b/devenv/kollanode.yaml new file mode 100644 index 0000000000..915c53a012 --- /dev/null +++ b/devenv/kollanode.yaml @@ -0,0 +1,199 @@ +heat_template_version: 2013-05-23 + +description: > + This is a nested stack that defines a single Kolla node, + based on a Fedora 21 cloud image. This stack is included by + a ResourceGroup resource in the parent template (kollacluster.yaml). + +parameters: + + server_image: + type: string + default: fedora-21-x86_64 + description: glance image used to boot the server + + server_flavor: + type: string + default: m1.small + description: flavor to use when booting the server + + ssh_key_name: + type: string + description: name of ssh key to be provisioned on our server + + external_network_id: + type: string + description: uuid of a network to use for kolla host floating ip addresses + + # The following are all generated in the parent template. + fixed_network_id: + type: string + description: Network from which to allocate fixed addresses. + fixed_subnet_id: + type: string + description: Subnet from which to allocate fixed addresses. + +resources: + + node_wait_handle: + type: "AWS::CloudFormation::WaitConditionHandle" + + node_wait_condition: + type: "AWS::CloudFormation::WaitCondition" + depends_on: + - kolla_node + properties: + Handle: + get_resource: node_wait_handle + Timeout: "6000" + + ###################################################################### + # + # security groups. we need to permit network traffic of various + # sorts. + # + secgroup_base: + type: "OS::Neutron::SecurityGroup" + properties: + rules: + - protocol: icmp + - protocol: tcp + port_range_min: 22 + port_range_max: 22 + + # Use by eth1 to permit all traffic to instances. + # Let the Neutron container apply security to this traffic. + secgroup_all_open: + type: "OS::Neutron::SecurityGroup" + properties: + rules: + - protocol: icmp + - protocol: tcp + - protocol: udp + + secgroup_kolla: + type: "OS::Neutron::SecurityGroup" + properties: + rules: + - protocol: tcp + port_range_min: 8773 + port_range_max: 8776 + - protocol: tcp + port_range_min: 6080 + port_range_max: 6080 + - protocol: tcp + port_range_min: 6081 + port_range_max: 6081 + - protocol: tcp + port_range_min: 35357 + port_range_max: 35357 + - protocol: tcp + port_range_min: 5000 + port_range_max: 5000 + - protocol: tcp + port_range_min: 9191 + port_range_max: 9191 + - protocol: tcp + port_range_min: 9292 + port_range_max: 9292 + - protocol: tcp + port_range_min: 9696 + port_range_max: 9696 + - protocol: tcp + port_range_min: 80 + port_range_max: 80 + - protocol: tcp + port_range_min: 443 + port_range_max: 443 + - protocol: tcp + port_range_min: 8000 + port_range_max: 8000 + - protocol: tcp + port_range_min: 8004 + port_range_max: 8004 + - protocol: tcp + port_range_min: 8003 + port_range_max: 8003 + - protocol: tcp + port_range_min: 8080 + port_range_max: 8080 + - protocol: tcp + port_range_min: 8777 + port_range_max: 8777 + + kolla_node: + type: "OS::Nova::Server" + properties: + image: + get_param: server_image + flavor: + get_param: server_flavor + key_name: + get_param: ssh_key_name + user_data_format: RAW + user_data: + str_replace: + template: | + #!/bin/sh + + yum -y upgrade + + yum -y remove NetworkManager + chkconfig network on + + # enable dnf command + yum -y install dnf dnf-plugins-core + + # Docker packages + dnf -y copr enable pkilambi/docker + dnf -y install docker + + # Start Docker + systemctl enable docker + systemctl start docker + + cfn-signal -e0 --data 'OK' -r 'Setup complete' '$WAIT_HANDLE' + params: + "$WAIT_HANDLE": + get_resource: node_wait_handle + networks: + - port: + get_resource: kolla_node_eth0 + - port: + get_resource: kolla_node_eth1 + + kolla_node_eth0: + type: "OS::Neutron::Port" + properties: + network_id: + get_param: fixed_network_id + security_groups: + - get_resource: secgroup_base + - get_resource: secgroup_kolla + fixed_ips: + - subnet_id: + get_param: fixed_subnet_id + + kolla_node_eth1: + type: "OS::Neutron::Port" + properties: + network_id: + get_param: external_network_id + security_groups: + - get_resource: secgroup_all_open + + kolla_node_floating: + type: "OS::Neutron::FloatingIP" + properties: + floating_network_id: + get_param: external_network_id + port_id: + get_resource: kolla_node_eth0 + +outputs: + + kolla_node_ip_eth0: + value: {get_attr: [kolla_node_eth0, fixed_ips, 0, ip_address]} + + kolla_node_external_ip: + value: {get_attr: [kolla_node_floating, floating_ip_address]} diff --git a/devenv/local.yaml.example b/devenv/local.yaml.example new file mode 100644 index 0000000000..b642526e26 --- /dev/null +++ b/devenv/local.yaml.example @@ -0,0 +1,3 @@ +parameters: + ssh_key_name: <YOUR_NOVA_KEYPAIR> + external_network_id: <NEUTRON_EXTERNAL_NET_ID> -- GitLab