Skip to content

Commit 1a225f9

Browse files
authored
CDB-34 Added Docker files and scripts to make the management API work with Astra-flavoured OSS distributions. (#15)
1 parent 41ea2db commit 1a225f9

File tree

6 files changed

+317
-32
lines changed

6 files changed

+317
-32
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
astra-4.0/*.tgz
12
target/
23
pom.xml.tag
34
pom.xml.releaseBackup

Dockerfile-astra-4_0

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
FROM management-api-for-apache-cassandra-builder as builder
2+
3+
FROM datastax/astra:4.0
4+
5+
COPY --from=builder /build/management-api-common/target/datastax-mgmtapi-common-0.1.0-SNAPSHOT.jar /etc/cassandra/
6+
COPY --from=builder /build/management-api-agent/target/datastax-mgmtapi-agent-0.1.0-SNAPSHOT.jar /etc/cassandra/
7+
COPY --from=builder /build/management-api-server/target/datastax-mgmtapi-server-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
8+
COPY --from=builder /build/management-api-shim-3.x/target/datastax-mgmtapi-shim-3.x-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
9+
COPY --from=builder /build/management-api-shim-4.x/target/datastax-mgmtapi-shim-4.x-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
10+
11+
ENV TINI_VERSION v0.18.0
12+
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
13+
RUN chmod +x /tini
14+
15+
RUN set -eux; \
16+
apt-get update; \
17+
apt-get install -y --no-install-recommends wget; \
18+
rm -rf /var/lib/apt/lists/*
19+
20+
ENV MCAC_VERSION 0.1.2
21+
ADD https://github.com/datastax/metric-collector-for-apache-cassandra/releases/download/v${MCAC_VERSION}/datastax-mcac-agent-${MCAC_VERSION}.tar.gz /opt/mcac-agent.tar.gz
22+
RUN mkdir /opt/mcac-agent && tar zxvf /opt/mcac-agent.tar.gz -C /opt/mcac-agent --strip-components 1 && rm /opt/mcac-agent.tar.gz
23+
24+
# backwards compat with upstream ENTRYPOINT
25+
COPY scripts/docker-entrypoint.sh /usr/local/bin/
26+
RUN chmod +x /usr/local/bin/docker-entrypoint.sh && \
27+
ln -sf /usr/local/bin/docker-entrypoint.sh /docker-entrypoint.sh
28+
29+
EXPOSE 9103
30+
EXPOSE 8080
31+
32+
ENTRYPOINT ["/docker-entrypoint.sh"]
33+
CMD ["mgmtapi"]

README.md

+22-2
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,37 @@
5151
is up to the caller. That being said, complex health checks can be added via CQL.
5252

5353
## Building
54-
Building for containers:
54+
55+
### Containers
56+
57+
First you need to build the Management API base image:
5558

5659
docker build -t management-api-for-apache-cassandra-builder -f ./Dockerfile-build .
60+
61+
Then you need to build the image based on the actual Cassandra® version, either the 3.11 or 4.0:
5762

5863
#Create a docker image with management api and C* 3.11
5964
docker build -t mgmtapi-3_11 -f Dockerfile-3_11 .
6065

6166
#Create a docker image with management api and C* 4.0
6267
docker build -t mgmtapi-4_0 -f Dockerfile-4_0 .
68+
69+
You can also build an image based on Datastax Astra Cassandra® 4.0 sources. First checkout [sources](https://github.com/datastax/cassandra/tree/astra) and build a tgz distribution:
70+
71+
ant artifacts
72+
73+
Then copy the tgz archive into the astra-4.0 directory of the Management API sources and run:
74+
75+
cd astra-4.0
76+
docker build -t datastax/astra:4.0 .
77+
78+
Finally build the Management API image:
79+
80+
cd ..
81+
docker build -t mgmtapi-astra-4_0 -f Dockerfile-astra-4_0 .
82+
6383

64-
Building for standalone:
84+
### Standalone
6585

6686
mvn -DskipTests package
6787
mvn test

astra-4.0/Dockerfile

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
FROM adoptopenjdk:8-jre-hotspot-bionic
2+
3+
# explicitly set user/group IDs
4+
RUN set -eux; \
5+
groupadd -r cassandra --gid=999; \
6+
useradd -r -g cassandra --uid=999 cassandra
7+
8+
RUN set -eux; \
9+
apt-get update; \
10+
apt-get install -y --no-install-recommends \
11+
# solves warning: "jemalloc shared library could not be preloaded to speed up memory allocations"
12+
libjemalloc1 \
13+
# "free" is used by cassandra-env.sh
14+
procps \
15+
# "cqlsh" needs a python interpreter
16+
python \
17+
# "ip" is not required by Cassandra itself, but is commonly used in scripting Cassandra's configuration (since it is so fixated on explicit IP addresses)
18+
iproute2 \
19+
# basic editing
20+
less \
21+
vim \
22+
# Cassandra will automatically use numactl if available
23+
# https://github.com/apache/cassandra/blob/18bcda2d4c2eba7370a0b21f33eed37cb730bbb3/bin/cassandra#L90-L100
24+
# https://github.com/apache/cassandra/commit/604c0e87dc67fa65f6904ef9a98a029c9f2f865a
25+
numactl \
26+
; \
27+
rm -rf /var/lib/apt/lists/*
28+
29+
# grab gosu for easy step-down from root
30+
ENV GOSU_VERSION 1.11
31+
RUN set -eux; \
32+
savedAptMark="$(apt-mark showmanual)"; \
33+
apt-get update; \
34+
apt-get install -y --no-install-recommends ca-certificates dirmngr gnupg wget; \
35+
rm -rf /var/lib/apt/lists/*; \
36+
dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \
37+
wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \
38+
wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \
39+
export GNUPGHOME="$(mktemp -d)"; \
40+
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
41+
gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
42+
gpgconf --kill all; \
43+
rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
44+
apt-mark auto '.*' > /dev/null; \
45+
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \
46+
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
47+
chmod +x /usr/local/bin/gosu; \
48+
gosu --version; \
49+
gosu nobody true
50+
51+
ENV CASSANDRA_HOME /opt/cassandra
52+
ENV CASSANDRA_CONF /etc/cassandra
53+
ENV PATH $CASSANDRA_HOME/bin:$PATH
54+
55+
COPY /cassandra-bin.tgz /
56+
57+
RUN mkdir -p "$CASSANDRA_HOME"; \
58+
tar --extract --file cassandra-bin.tgz --directory "$CASSANDRA_HOME" --strip-components 1; \
59+
rm cassandra-bin.tgz*; \
60+
\
61+
[ ! -e "$CASSANDRA_CONF" ]; \
62+
mv "$CASSANDRA_HOME/conf" "$CASSANDRA_CONF"; \
63+
ln -sT "$CASSANDRA_CONF" "$CASSANDRA_HOME/conf"; \
64+
\
65+
dpkgArch="$(dpkg --print-architecture)"; \
66+
case "$dpkgArch" in \
67+
ppc64el) \
68+
# https://issues.apache.org/jira/browse/CASSANDRA-13345
69+
# "The stack size specified is too small, Specify at least 328k"
70+
if grep -q -- '^-Xss' "$CASSANDRA_CONF/jvm.options"; then \
71+
# 3.11+ (jvm.options)
72+
grep -- '^-Xss256k$' "$CASSANDRA_CONF/jvm.options"; \
73+
sed -ri 's/^-Xss256k$/-Xss512k/' "$CASSANDRA_CONF/jvm.options"; \
74+
grep -- '^-Xss512k$' "$CASSANDRA_CONF/jvm.options"; \
75+
elif grep -q -- '-Xss256k' "$CASSANDRA_CONF/cassandra-env.sh"; then \
76+
# 3.0 (cassandra-env.sh)
77+
sed -ri 's/-Xss256k/-Xss512k/g' "$CASSANDRA_CONF/cassandra-env.sh"; \
78+
grep -- '-Xss512k' "$CASSANDRA_CONF/cassandra-env.sh"; \
79+
fi; \
80+
;; \
81+
esac; \
82+
\
83+
mkdir -p "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra; \
84+
chown -R cassandra:cassandra "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra; \
85+
chmod 777 "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra; \
86+
ln -sT /var/lib/cassandra "$CASSANDRA_HOME/data"; \
87+
ln -sT /var/log/cassandra "$CASSANDRA_HOME/logs"; \
88+
\
89+
# smoke test
90+
cassandra -v
91+
92+
VOLUME /var/lib/cassandra
93+
94+
COPY docker-entrypoint.sh /usr/local/bin/
95+
RUN ln -s usr/local/bin/docker-entrypoint.sh /docker-entrypoint.sh # backwards compat
96+
97+
# 7000: intra-node communication
98+
# 7001: TLS intra-node communication
99+
# 7199: JMX
100+
# 9042: CQL
101+
# 9160: thrift service
102+
EXPOSE 7000 7001 7199 9042 9160
103+
104+
ENTRYPOINT ["docker-entrypoint.sh"]
105+
CMD ["cassandra", "-f"]

astra-4.0/docker-entrypoint.sh

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# first arg is `-f` or `--some-option`
5+
# or there are no args
6+
if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
7+
set -- cassandra -f "$@"
8+
fi
9+
10+
# allow the container to be started with `--user`
11+
if [ "$1" = 'cassandra' -a "$(id -u)" = '0' ]; then
12+
find "$CASSANDRA_CONF" /var/lib/cassandra /var/log/cassandra \
13+
\! -user cassandra -exec chown cassandra '{}' +
14+
exec gosu cassandra "$BASH_SOURCE" "$@"
15+
fi
16+
17+
_ip_address() {
18+
# scrape the first non-localhost IP address of the container
19+
# in Swarm Mode, we often get two IPs -- the container IP, and the (shared) VIP, and the container IP should always be first
20+
ip address | awk '
21+
$1 == "inet" && $NF != "lo" {
22+
gsub(/\/.+$/, "", $2)
23+
print $2
24+
exit
25+
}
26+
'
27+
}
28+
29+
# "sed -i", but without "mv" (which doesn't work on a bind-mounted file, for example)
30+
_sed-in-place() {
31+
local filename="$1"; shift
32+
local tempFile
33+
tempFile="$(mktemp)"
34+
sed "$@" "$filename" > "$tempFile"
35+
cat "$tempFile" > "$filename"
36+
rm "$tempFile"
37+
}
38+
39+
if [ "$1" = 'cassandra' ]; then
40+
: ${CASSANDRA_RPC_ADDRESS='0.0.0.0'}
41+
42+
: ${CASSANDRA_LISTEN_ADDRESS='auto'}
43+
if [ "$CASSANDRA_LISTEN_ADDRESS" = 'auto' ]; then
44+
CASSANDRA_LISTEN_ADDRESS="$(_ip_address)"
45+
fi
46+
47+
: ${CASSANDRA_BROADCAST_ADDRESS="$CASSANDRA_LISTEN_ADDRESS"}
48+
49+
if [ "$CASSANDRA_BROADCAST_ADDRESS" = 'auto' ]; then
50+
CASSANDRA_BROADCAST_ADDRESS="$(_ip_address)"
51+
fi
52+
: ${CASSANDRA_BROADCAST_RPC_ADDRESS:=$CASSANDRA_BROADCAST_ADDRESS}
53+
54+
if [ -n "${CASSANDRA_NAME:+1}" ]; then
55+
: ${CASSANDRA_SEEDS:="cassandra"}
56+
fi
57+
: ${CASSANDRA_SEEDS:="$CASSANDRA_BROADCAST_ADDRESS"}
58+
59+
CASSANDRA_YAML="cassandra.yaml"
60+
if [ $CASSANDRA_DEPLOYMENT ]; then
61+
CASSANDRA_DEPLOYMENT=`echo "$CASSANDRA_DEPLOYMENT" | awk '{print tolower($0)}'`
62+
CASSANDRA_YAML="cassandra-$CASSANDRA_DEPLOYMENT.yaml"
63+
fi
64+
65+
_sed-in-place "$CASSANDRA_CONF/$CASSANDRA_YAML" \
66+
-r 's/(- seeds:).*/\1 "'"$CASSANDRA_SEEDS"'"/'
67+
68+
for yaml in \
69+
broadcast_address \
70+
broadcast_rpc_address \
71+
cluster_name \
72+
endpoint_snitch \
73+
listen_address \
74+
num_tokens \
75+
rpc_address \
76+
start_rpc \
77+
; do
78+
var="CASSANDRA_${yaml^^}"
79+
val="${!var}"
80+
if [ "$val" ]; then
81+
_sed-in-place "$CASSANDRA_CONF/$CASSANDRA_YAML" \
82+
-r 's/^(# )?('"$yaml"':).*/\2 '"$val"'/'
83+
fi
84+
done
85+
86+
for rackdc in dc rack; do
87+
var="CASSANDRA_${rackdc^^}"
88+
val="${!var}"
89+
if [ "$val" ]; then
90+
_sed-in-place "$CASSANDRA_CONF/cassandra-rackdc.properties" \
91+
-r 's/^('"$rackdc"'=).*/\1 '"$val"'/'
92+
fi
93+
done
94+
fi
95+
96+
exec $@

scripts/docker-entrypoint.sh

+60-30
Original file line numberDiff line numberDiff line change
@@ -70,36 +70,66 @@ if [ "$1" = 'mgmtapi' ]; then
7070
echo "JVM_OPTS=\"\$JVM_OPTS -javaagent:/etc/cassandra/datastax-mgmtapi-agent-0.1.0-SNAPSHOT.jar\"" >> /etc/cassandra/cassandra-env.sh
7171
fi
7272

73-
CASSANDRA_RPC_ADDRESS='0.0.0.0'
74-
CASSANDRA_BROADCAST_RPC_ADDRESS="$(_ip_address)"
75-
76-
# Not needed as the operator will set all this but leaving for testing
77-
for yaml in \
78-
cluster_name \
79-
endpoint_snitch \
80-
num_tokens \
81-
start_rpc \
82-
broadcast_address \
83-
broadcast_rpc_address \
84-
listen_address \
85-
rpc_address \
86-
; do
87-
var="CASSANDRA_${yaml^^}"
88-
val="${!var}"
89-
if [ "$val" ]; then
90-
_sed-in-place "$CASSANDRA_CONF/cassandra.yaml" \
91-
-r 's/^(# )?('"$yaml"':).*/\2 '"$val"'/'
92-
fi
93-
done
94-
95-
# for rackdc in dc rack; do
96-
# var="CASSANDRA_${rackdc^^}"
97-
# val="${!var}"
98-
# if [ "$val" ]; then
99-
# _sed-in-place "$CASSANDRA_CONF/cassandra-rackdc.properties" \
100-
# -r 's/^('"$rackdc"'=).*/\1 '"$val"'/'
101-
# fi
102-
# done
73+
# Set this if you want to ignore default env variables, i.e. when running inside an operator
74+
if [ $IGNORE_DEFAULTS ]; then
75+
CASSANDRA_RPC_ADDRESS='0.0.0.0'
76+
CASSANDRA_BROADCAST_RPC_ADDRESS="$(_ip_address)"
77+
else
78+
: ${CASSANDRA_RPC_ADDRESS='0.0.0.0'}
79+
80+
: ${CASSANDRA_LISTEN_ADDRESS='auto'}
81+
if [ "$CASSANDRA_LISTEN_ADDRESS" = 'auto' ]; then
82+
CASSANDRA_LISTEN_ADDRESS="$(_ip_address)"
83+
fi
84+
85+
: ${CASSANDRA_BROADCAST_ADDRESS="$CASSANDRA_LISTEN_ADDRESS"}
86+
87+
if [ "$CASSANDRA_BROADCAST_ADDRESS" = 'auto' ]; then
88+
CASSANDRA_BROADCAST_ADDRESS="$(_ip_address)"
89+
fi
90+
: ${CASSANDRA_BROADCAST_RPC_ADDRESS:=$CASSANDRA_BROADCAST_ADDRESS}
91+
92+
if [ -n "${CASSANDRA_NAME:+1}" ]; then
93+
: ${CASSANDRA_SEEDS:="cassandra"}
94+
fi
95+
: ${CASSANDRA_SEEDS:="$CASSANDRA_BROADCAST_ADDRESS"}
96+
97+
CASSANDRA_YAML="cassandra.yaml"
98+
if [ $CASSANDRA_DEPLOYMENT ]; then
99+
CASSANDRA_DEPLOYMENT=`echo "$CASSANDRA_DEPLOYMENT" | awk '{print tolower($0)}'`
100+
CASSANDRA_YAML="cassandra-$CASSANDRA_DEPLOYMENT.yaml"
101+
fi
102+
103+
_sed-in-place "$CASSANDRA_CONF/$CASSANDRA_YAML" \
104+
-r 's/(- seeds:).*/\1 "'"$CASSANDRA_SEEDS"'"/'
105+
106+
for yaml in \
107+
broadcast_address \
108+
broadcast_rpc_address \
109+
cluster_name \
110+
endpoint_snitch \
111+
listen_address \
112+
num_tokens \
113+
rpc_address \
114+
start_rpc \
115+
; do
116+
var="CASSANDRA_${yaml^^}"
117+
val="${!var}"
118+
if [ "$val" ]; then
119+
_sed-in-place "$CASSANDRA_CONF/$CASSANDRA_YAML" \
120+
-r 's/^(# )?('"$yaml"':).*/\2 '"$val"'/'
121+
fi
122+
done
123+
124+
for rackdc in dc rack; do
125+
var="CASSANDRA_${rackdc^^}"
126+
val="${!var}"
127+
if [ "$val" ]; then
128+
_sed-in-place "$CASSANDRA_CONF/cassandra-rackdc.properties" \
129+
-r 's/^('"$rackdc"'=).*/\1 '"$val"'/'
130+
fi
131+
done
132+
fi
103133

104134
MGMT_API_ARGS=""
105135

0 commit comments

Comments
 (0)