Browse code

Added clustered etcd example

Michal Fojtik authored on 2015/05/06 23:31:39
Showing 6 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,26 @@
0
+FROM centos:centos7
1
+MAINTAINER http://openshift.io
2
+
3
+RUN yum install -y tar bind-utils && yum clean all
4
+
5
+ENV ETCD_RELEASE v2.0.10
6
+
7
+LABEL k8s.io/description="A highly-available key-value store for shared configuration and service discovery" \
8
+      k8s.io/display-name="etcd v2.0.10" \
9
+      openshift.io/expose-services="2379:http,2380:etcd" \
10
+      openshift.io/tags="database,etcd,etcd20"
11
+
12
+RUN ETCD_URL=https://github.com/coreos/etcd/releases/download/${ETCD_RELEASE}/etcd-${ETCD_RELEASE}-linux-amd64.tar.gz && \
13
+  mkdir -p /tmp/etcd && cd /tmp/etcd && \
14
+  curl -L ${ETCD_URL} | tar -xzf - --strip-components=1 && \
15
+  mv {etcd,etcdctl} /usr/local/bin/ && \
16
+  mkdir -p /var/lib/etcd && \
17
+  rm -rf /tmp/etcd
18
+
19
+EXPOSE 2379 2380
20
+
21
+VOLUME ["/var/lib/etcd"]
22
+
23
+ADD etcd*.sh /usr/local/bin/
24
+
25
+CMD ["/usr/local/bin/etcd.sh"]
0 26
new file mode 100644
... ...
@@ -0,0 +1,2 @@
0
+all:
1
+	docker build -t openshift/etcd-20-centos7 .
0 2
new file mode 100644
... ...
@@ -0,0 +1,71 @@
0
+Clustered etcd Template
1
+========================
2
+
3
+etcd is a distributed, consistent key value store for shared configuration and
4
+service discovery. For more details about etcd, visit:
5
+
6
+https://github.com/coreos/etcd
7
+
8
+### Requirements
9
+
10
+You can 'pre-pull' the Docker image used by this template by:
11
+
12
+```
13
+$ docker pull openshift/etcd-20-centos7
14
+```
15
+
16
+You can also build this Docker image yourself, by using provided Makefile:
17
+
18
+```
19
+$ make
20
+```
21
+
22
+### How to use this template
23
+
24
+You can import this template to OpenShift using:
25
+
26
+```
27
+$ osc create -f examples/etcd/template.json
28
+```
29
+
30
+Then you can navigate to OpenShift UI and click the 'Create' button on top right
31
+and choose 'Browse templates...'. Choose the 'etcd' and hit create.
32
+
33
+Another way, is to use the CLI only:
34
+
35
+```
36
+$ osc process -f examples/etcd/template.json | osc create -f -
37
+```
38
+
39
+### How does it work
40
+
41
+This template creates two Services. The first service is used for initial
42
+discovery and stores information about running members. This service is used
43
+only internally by the cluster members and you should not need to access it.
44
+You can however obtain information about the current state/size of the cluster.
45
+
46
+The second service 'etcd' is the main entrypoint for accessing the 'etcd'
47
+cluster. This service is exposing two ports. The port 2380 is used for internal
48
+server-to-server communication and the port 2379 is used for the client
49
+connections.
50
+
51
+The 'etcd-discovery' pod created by this template will create an instance of
52
+etcd server, that is used as cluster discovery service. This pod can be stopped
53
+or deleted when desired size of the cluster is reached. If you want to add more
54
+members you will have to start this pod again manually.
55
+
56
+The 'etcd' replication controller manage creation of the etcd cluster members.
57
+By default this template will start 3 members. The members then register
58
+themselves using the discovery service and elect the leader. You can adjust the
59
+number of replicas as long as the 'etcd-discovery' service is running.
60
+
61
+### Cleaning up
62
+
63
+If you're done playing, you can remove all the created resources by executing
64
+following command:
65
+
66
+```
67
+$ ./examples/etcd/teardown.sh
68
+```
69
+
70
+Note: This will also remove all data you have stored in the etcd.
0 71
new file mode 100755
... ...
@@ -0,0 +1,12 @@
0
+#!/bin/bash -e
1
+#
2
+# This is a wrapper for the etcd that serves as 'discovery' server and manager
3
+# for the cluster configuration
4
+
5
+address=$(getent ahosts ${HOSTNAME} | grep RAW | cut -d ' ' -f 1)
6
+
7
+exec /usr/local/bin/etcd \
8
+  -advertise-client-urls http://${address}:2379 \
9
+  -listen-client-urls http://${address}:2379 \
10
+  -data-dir /var/lib/etcd \
11
+  -name discovery
0 12
new file mode 100755
... ...
@@ -0,0 +1,28 @@
0
+#!/bin/bash
1
+#
2
+# This is a wrapper script for the etcd command.
3
+# This wrapper detects the presence of ETCD_DISCOVERY environment variable and
4
+# if this variable is set then it will use DNS lookup to collect the IP
5
+# addresses of the other members of the cluster. This wrapper then adjust the
6
+# size of the cluster in the discovery service and register itself.
7
+
8
+# If we are not running in cluster, then just execute the etcd binary
9
+if [[ -z "${ETCD_DISCOVERY-}" ]]; then
10
+  exec /usr/local/bin/etcd "$@"
11
+fi
12
+
13
+address=$(getent ahosts ${HOSTNAME} | grep RAW | cut -d ' ' -f 1)
14
+
15
+curl -sX PUT ${ETCD_DISCOVERY}/_config/size -d value=${ETCD_NUM_MEMBERS}
16
+
17
+# Adding UNIX timestamp prevents having duplicate member id's
18
+member_id="${HOSTNAME}-$(date +"%s")"
19
+
20
+echo "Starting member ${member_id} (${address})..."
21
+exec /usr/local/bin/etcd \
22
+  -initial-advertise-peer-urls http://${address}:2380 \
23
+  -listen-peer-urls http://${address}:2380 \
24
+  -advertise-client-urls http://${address}:2379 \
25
+  -listen-client-urls http://${address}:2379 \
26
+  -data-dir /var/lib/etcd \
27
+  -name ${member_id}
0 28
new file mode 100644
... ...
@@ -0,0 +1,222 @@
0
+{
1
+  "kind": "Template",
2
+  "apiVersion": "v1beta1",
3
+  "labels": {
4
+    "template": "etcd"
5
+  },
6
+  "metadata": {
7
+    "annotations": {
8
+      "description": "Example of clustered etcd",
9
+      "tags": "database,etcd",
10
+      "iconClass" : "icon-database"
11
+    },
12
+    "name": "etcd"
13
+  },
14
+  "parameters": [
15
+    {
16
+      "name": "ETCD_IMAGE",
17
+      "description": "The name of etcd Docker image to use",
18
+      "value": "openshift/etcd-20-centos7"
19
+    },
20
+    {
21
+      "name": "ETCD_NUM_MEMBERS",
22
+      "description": "Maximum number of members to launch (have to match with # of replicas)",
23
+      "value": "3"
24
+    },
25
+    {
26
+      "name": "ETCD_DISCOVERY",
27
+      "description": "A token used for etcd discovery",
28
+      "from": "http://etcd-discovery:2379/v2/keys/discovery/[a-z0-9]{40}",
29
+      "generate": "expression"
30
+    },
31
+    {
32
+      "name": "ETCD_CLUSTER_TOKEN",
33
+      "description": "A token etcd use to generate unique cluster ID and member ID",
34
+      "from": "etcd-cluster-[a-z0-9]{5}",
35
+      "generate": "expression"
36
+    }
37
+  ],
38
+  "items":[
39
+    {
40
+      "apiVersion": "v1beta1",
41
+      "kind": "ImageStream",
42
+      "metadata": {
43
+        "name": "etcd"
44
+      },
45
+      "spec": {
46
+        "dockerImageRepository": "${ETCD_IMAGE}",
47
+        "tags": [
48
+          {
49
+            "name": "latest",
50
+            "annotations": {
51
+              "description": "Provides etcd v2.0.10",
52
+              "iconClass": "icon-database",
53
+              "tags": "database,etcd",
54
+              "version": "2.0.10"
55
+            }
56
+          }
57
+        ]
58
+      }
59
+    },
60
+    {
61
+      "kind": "Service",
62
+      "apiVersion": "v1beta3",
63
+      "metadata": {
64
+        "name": "etcd-discovery",
65
+        "labels": {
66
+          "name": "etcd-discovery"
67
+        }
68
+      },
69
+      "spec": {
70
+        "portalIp": "None",
71
+        "ports": [
72
+          {
73
+            "port": 2379,
74
+            "targetPort": 2379
75
+          }
76
+        ],
77
+        "selector": {
78
+          "name": "etcd-discovery"
79
+        }
80
+      }
81
+    },
82
+    {
83
+      "kind": "Service",
84
+      "apiVersion": "v1beta3",
85
+      "metadata": {
86
+        "name": "etcd",
87
+        "labels": {
88
+          "name": "etcd"
89
+        }
90
+      },
91
+      "spec": {
92
+        "portalIP": "None",
93
+        "ports": [
94
+          {
95
+            "name": "client",
96
+            "port": 2379,
97
+            "targetPort": 2379
98
+          },
99
+          {
100
+            "name": "server",
101
+            "port": 2380,
102
+            "targetPort": 2380
103
+          }
104
+        ],
105
+        "selector": {
106
+          "name": "etcd"
107
+        }
108
+      }
109
+    },
110
+    {
111
+      "apiVersion": "v1beta1",
112
+      "kind": "DeploymentConfig",
113
+      "metadata": {
114
+        "name": "etcd-discovery"
115
+      },
116
+      "template": {
117
+        "controllerTemplate": {
118
+          "podTemplate": {
119
+            "desiredState": {
120
+              "manifest": {
121
+                "containers":[
122
+                  {
123
+                    "name":  "discovery",
124
+                    "image": "${ETCD_IMAGE}",
125
+                    "command": ["etcd-discovery.sh"],
126
+                    "ports":[
127
+                      {
128
+                        "containerPort": 2379
129
+                      }
130
+                    ]
131
+                  }
132
+                ],
133
+                "version": "v1beta1"
134
+              }
135
+            },
136
+            "labels": {
137
+              "name": "etcd-discovery"
138
+            }
139
+          },
140
+          "replicaSelector": {
141
+            "name": "etcd-discovery"
142
+          },
143
+          "replicas": 1
144
+        },
145
+        "strategy": {
146
+          "type": "Recreate"
147
+        }
148
+      },
149
+      "triggers": [
150
+        {
151
+          "type": "ConfigChange"
152
+        }
153
+      ]
154
+    },   
155
+    {
156
+      "apiVersion": "v1beta1",
157
+      "kind": "DeploymentConfig",
158
+      "metadata": {
159
+        "name": "etcd"
160
+      },
161
+      "template": {
162
+        "controllerTemplate": {
163
+          "podTemplate": {
164
+            "desiredState": {
165
+              "manifest": {
166
+                "containers":[
167
+                  {
168
+                    "name":  "member",
169
+                    "image": "${ETCD_IMAGE}",
170
+                    "env": [
171
+                      {
172
+                        "name": "ETCD_NUM_MEMBERS",
173
+                        "value": "${ETCD_NUM_MEMBERS}"
174
+                      },
175
+                      {
176
+                        "name": "ETCD_INITIAL_CLUSTER_STATE",
177
+                        "value": "new"
178
+                      },
179
+                      {
180
+                        "name": "ETCD_INITIAL_CLUSTER_TOKEN",
181
+                        "value": "${ETCD_CLUSTER_TOKEN}"
182
+                      },
183
+                      {
184
+                        "name": "ETCD_DISCOVERY",
185
+                        "value": "${ETCD_DISCOVERY}"
186
+                      }
187
+                    ],
188
+                    "ports":[
189
+                      {
190
+                        "containerPort": 2379
191
+                      },
192
+                      {
193
+                        "containerPort": 2380
194
+                      }
195
+                    ]
196
+                  }
197
+                ],
198
+                "version": "v1beta1"
199
+              }
200
+            },
201
+            "labels": {
202
+              "name": "etcd"
203
+            }
204
+          },
205
+          "replicaSelector": {
206
+            "name": "etcd"
207
+          },
208
+          "replicas": 3
209
+        },
210
+        "strategy": {
211
+          "type": "Recreate"
212
+        }
213
+      },
214
+      "triggers": [
215
+        {
216
+          "type": "ConfigChange"
217
+        }
218
+      ]
219
+    }    
220
+  ]
221
+}