Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Experimental arm64 support for Cassandra 3.11.6 #36

Merged
merged 18 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ jobs:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Setup Buildx
id: buildx
uses: crazy-max/ghaction-docker-buildx@v3
with:
version: latest
- name: Build Management API in docker
run: |
cat <<EOF > ~/.m2/settings.xml
Expand All @@ -39,7 +44,11 @@ jobs:
cp ~/.m2/settings.xml settings.xml
docker build -t management-api-for-dse-builder -f ./Dockerfile-build-dse ./
docker tag management-api-for-dse-builder management-api-for-apache-cassandra-builder
docker build -t mgmtapi-3_11 -f Dockerfile-3_11 .
docker buildx build \
--tag mgmtapi-3_11 \
--file Dockerfile-oss \
--target oss311 \
--platform linux/amd64,linux/arm64 .
docker build -t mgmtapi-4_0 -f Dockerfile-4_0 .
docker build -t mgmtapi-dse-68 -f Dockerfile-dse-68 .
- name: Build with Maven
Expand Down
33 changes: 22 additions & 11 deletions .github/workflows/docker-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- 'v*.*.*'

jobs:
build:
build-dse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
Expand All @@ -32,14 +32,14 @@ jobs:
cp ~/.m2/settings.xml settings.xml
docker build -t management-api-for-dse-builder -f ./Dockerfile-build-dse ./
docker tag management-api-for-dse-builder management-api-for-apache-cassandra-builder
- name: Publish 3.11 to Registry
- name: Publish DSE 6.8 to Registry
uses: elgohr/Publish-Docker-Github-Action@master
with:
name: datastax/cassandra-mgmtapi-3_11_7
name: datastax/dse-mgmtapi-6_8
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
tag_names: true
dockerfile: Dockerfile-3_11
dockerfile: Dockerfile-dse-68
- name: Publish 4.0 to Registry
uses: elgohr/Publish-Docker-Github-Action@master
with:
Expand All @@ -48,11 +48,22 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }}
tag_names: true
dockerfile: Dockerfile-4_0
- name: Publish DSE 6.8 to Registry
uses: elgohr/Publish-Docker-Github-Action@master
build-oss:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Setup Buildx
id: buildx
uses: crazy-max/ghaction-docker-buildx@v3
with:
name: datastax/dse-mgmtapi-6_8
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
tag_names: true
dockerfile: Dockerfile-dse-68
version: latest
- name: Login to Docker Hub
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Publish 3.11 to Registry
run: |
RELEASE_VERSION="${GITHUB_REF##*/}"
docker buildx build --push \
--tag datastax/cassandra-mgmtapi-3_11_7:$RELEASE_VERSION \
--file Dockerfile-oss \
--target oss311 \
--platform linux/amd64,linux/arm64 .
115 changes: 115 additions & 0 deletions Dockerfile-oss
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
FROM --platform=$BUILDPLATFORM maven:3.6.3-jdk-8-slim as builder
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using buildx, there isn't a way to make a build of an image in one invocation of buildx available to a subsequent invocation of buildx without the use of a registry. This means our traditional approach of having a 'build' docker image that we then reference in subsequent docker files will not work (unless we push it to a registry). To get around this, we use one multi-stage docker file that contains the build stages. A further discussion of this issue in buildx can be found here: docker/buildx#156

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, note the --platform=$BUILDPLATFORM. This is because we don't have to build the jar for each arch we support since its java. This indicates that this stage should only be built on whatever the build platform is (probably linux-amd64).


WORKDIR /build

COPY pom.xml ./
COPY management-api-agent/pom.xml ./management-api-agent/pom.xml
COPY management-api-common/pom.xml ./management-api-common/pom.xml
COPY management-api-server/pom.xml ./management-api-server/pom.xml
COPY management-api-shim-3.x/pom.xml ./management-api-shim-3.x/pom.xml
COPY management-api-shim-4.x/pom.xml ./management-api-shim-4.x/pom.xml
# this duplicates work done in the next steps, but this should provide
# a solid cache layer that only gets reset on pom.xml changes
RUN mvn -q -ff -T 1C install && rm -rf target

COPY management-api-agent ./management-api-agent
COPY management-api-common ./management-api-common
COPY management-api-server ./management-api-server
COPY management-api-shim-3.x ./management-api-shim-3.x
COPY management-api-shim-4.x ./management-api-shim-4.x
RUN mvn -q -ff package -DskipTests

FROM --platform=$BUILDPLATFORM maven:3.6.3-jdk-8-slim as netty4150
RUN mvn dependency:get -DgroupId=io.netty -DartifactId=netty-all -Dversion=4.1.50.Final -Dtransitive=false

FROM --platform=linux/amd64 cassandra:3.11.7 as oss311-amd64

FROM --platform=linux/arm64 cassandra:3.11.7 as oss311-arm64
# Netty arm64 epoll support was not added until 4.1.50 (https://github.com/netty/netty/pull/9804)
# Only replace this dependency for arm64 to avoid regressions
RUN rm /opt/cassandra/lib/netty-all-*.jar
COPY --from=netty4150 /root/.m2/repository/io/netty/netty-all/4.1.50.Final/netty-all-4.1.50.Final.jar /opt/cassandra/lib/netty-all-4.1.50.Final.jar
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The better way to do this is probably to have the management api agent contain a shaded version of netty at the appropriate version. That will take further experimentation. However, we are only swapping out this jar for arm64, so this should not impact any existing users.


FROM oss311-${TARGETARCH} as oss311

ARG TARGETARCH

COPY --from=builder /build/management-api-common/target/datastax-mgmtapi-common-0.1.0-SNAPSHOT.jar /etc/cassandra/
COPY --from=builder /build/management-api-agent/target/datastax-mgmtapi-agent-0.1.0-SNAPSHOT.jar /etc/cassandra/
COPY --from=builder /build/management-api-server/target/datastax-mgmtapi-server-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
COPY --from=builder /build/management-api-shim-3.x/target/datastax-mgmtapi-shim-3.x-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
COPY --from=builder /build/management-api-shim-4.x/target/datastax-mgmtapi-shim-4.x-0.1.0-SNAPSHOT.jar /opt/mgmtapi/

ENV TINI_VERSION v0.18.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the change here to get tini for the appropriate architecture.

RUN chmod +x /tini

RUN set -eux; \
rm -fr /etc/apt/sources.list.d/*; \
rm -rf /var/lib/apt/lists/*; \
apt-get update; \
apt-get install -y --no-install-recommends wget iproute2; \
rm -rf /var/lib/apt/lists/*

ENV MCAC_VERSION 0.1.7
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
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

# backwards compat with upstream ENTRYPOINT
COPY scripts/docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh && \
ln -sf /usr/local/bin/docker-entrypoint.sh /docker-entrypoint.sh

EXPOSE 9103
EXPOSE 8080

ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["mgmtapi"]


# NOTE: Presently, OSS doesn't have official Cassandra 4.0 builds on dockerhub
# and our build at datastax/cassandra:4.0 is not a multiarch image like the
# official ones. Once one of those issues is fixed, the following targets can
# be used to build Cassandra 4.0 with Management API.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Half way through this I realized we didn't have an appropriate multiarch cassandra 4.0 image. We could just remove all of this for now instead of commenting out. I thought it might be useful for reference, but I have no strong feelings either way.


# FROM --platform=linux/amd64 cassandra:4.0 as oss40-amd64

# FROM --platform=linux/arm64 cassandra:4.0 as oss40-arm64
# # Netty arm64 epoll support was not added until 4.1.50 (https://github.com/netty/netty/pull/9804)
# # Only replace this dependency for arm64 to avoid regressions
# RUN rm /opt/cassandra/lib/netty-all-*.jar
# COPY --from=netty4150 /root/.m2/repository/io/netty/netty-all/4.1.50.Final/netty-all-4.1.50.Final.jar /opt/cassandra/lib/netty-all-4.1.50.Final.jar

# FROM oss40-${TARGETARCH} as oss40

# ARG TARGETARCH

# COPY --from=builder /build/management-api-common/target/datastax-mgmtapi-common-0.1.0-SNAPSHOT.jar /etc/cassandra/
# COPY --from=builder /build/management-api-agent/target/datastax-mgmtapi-agent-0.1.0-SNAPSHOT.jar /etc/cassandra/
# COPY --from=builder /build/management-api-server/target/datastax-mgmtapi-server-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
# COPY --from=builder /build/management-api-shim-3.x/target/datastax-mgmtapi-shim-3.x-0.1.0-SNAPSHOT.jar /opt/mgmtapi/
# COPY --from=builder /build/management-api-shim-4.x/target/datastax-mgmtapi-shim-4.x-0.1.0-SNAPSHOT.jar /opt/mgmtapi/

# ENV TINI_VERSION v0.18.0
# ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} /tini
# RUN chmod +x /tini

# RUN set -eux; \
# apt-get update; \
# apt-get install -y --no-install-recommends wget iproute2; \
# rm -rf /var/lib/apt/lists/*

# ENV MCAC_VERSION 0.1.7
# 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
# 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

# # backwards compat with upstream ENTRYPOINT
# COPY scripts/docker-entrypoint.sh /usr/local/bin/
# RUN chmod +x /usr/local/bin/docker-entrypoint.sh && \
# ln -sf /usr/local/bin/docker-entrypoint.sh /docker-entrypoint.sh

# EXPOSE 9103
# EXPOSE 8080

# ENTRYPOINT ["/docker-entrypoint.sh"]
# CMD ["mgmtapi"]
2 changes: 1 addition & 1 deletion management-api-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<properties>
<slf4j.version>1.7.25</slf4j.version>
<logback.version>1.2.3</logback.version>
<netty.version>4.1.45.Final</netty.version>
<netty.version>4.1.50.Final</netty.version>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one provides a build of epoll for arm64.

<cassandra.version>3.11.5</cassandra.version>
</properties>

Expand Down
2 changes: 1 addition & 1 deletion management-api-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<airline.version>2.7.0</airline.version>
<jaxrs.version>2.0.8</jaxrs.version>
<resteasy.version>4.0.0.Final</resteasy.version>
<netty.version>4.1.45.Final</netty.version>
<netty.version>4.1.50.Final</netty.version>
<driver.version>4.4.0</driver.version>
<docker.java.version>3.1.2</docker.java.version>
<cassandra.version>3.11.5</cassandra.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,23 @@ public String getIpAddressOfContainer()
public void startManagementAPI(String version, List<String> envVars)
{
File baseDir = new File(System.getProperty("dockerFileRoot","."));
File dockerFile = Paths.get(baseDir.getPath(), "Dockerfile-" + version).toFile();
File dockerFile;
String target;
boolean useBuildx;

if ("3_11".equals(version))
{
dockerFile = Paths.get(baseDir.getPath(), "Dockerfile-oss").toFile();
target = "oss311";
useBuildx = true;
}
else
{
dockerFile = Paths.get(baseDir.getPath(), "Dockerfile-" + version).toFile();
target = null;
useBuildx = false;
}

if (!dockerFile.exists())
throw new RuntimeException("Missing " + dockerFile.getAbsolutePath());

Expand All @@ -79,7 +95,7 @@ public void startManagementAPI(String version, List<String> envVars)
if (envVars != null)
envList.addAll(envVars);

this.container = startDocker(dockerFile, baseDir, name, ports, volumeDescList, envList, cmdList);
this.container = startDocker(dockerFile, baseDir, target, name, ports, volumeDescList, envList, cmdList, useBuildx);

waitForPort("localhost",8080, Duration.ofMillis(50000), logger, false);
}
Expand Down Expand Up @@ -159,7 +175,29 @@ public boolean started()
return container != null;
}

private String startDocker(File dockerFile, File baseDir, String name, List<Integer> ports, List<String> volumeDescList, List<String> envList, List<String> cmdList)
private void buildImageWithBuildx(File dockerFile, File baseDir, String target, String name) throws Exception {
ProcessBuilder pb = new ProcessBuilder("docker", "buildx", "build",
"--load",
"--tag", name,
"--file", dockerFile.getPath(),
"--target", target,
"--platform", "linux/amd64",
baseDir.getPath());

Process p = pb.inheritIO().start();
int exitCode = p.waitFor();

if (exitCode != 0)
{
throw new Exception("Command '" + String.join(" ", pb.command() + "' return error code: " + exitCode));
}
}
private String startDocker(File dockerFile, File baseDir, String target, String name, List<Integer> ports, List<String> volumeDescList, List<String> envList, List<String> cmdList)
{
return startDocker(dockerFile, baseDir, target, name, ports, volumeDescList, envList, cmdList, false);
}

private String startDocker(File dockerFile, File baseDir, String target, String name, List<Integer> ports, List<String> volumeDescList, List<String> envList, List<String> cmdList, boolean useBuildx)
{
ListContainersCmd listContainersCmd = dockerClient.listContainersCmd();
listContainersCmd.getFilters().put("name", Arrays.asList(name));
Expand Down Expand Up @@ -200,12 +238,27 @@ public void onNext(BuildResponseItem item)
};

logger.info("Building container: " + name + " from " + dockerFile);
dockerClient.buildImageCmd()
if (useBuildx)
{
try
{
buildImageWithBuildx(dockerFile, baseDir, target, name);
}
catch (Exception e)
{
e.printStackTrace();
logger.error("Unable to build image");
}
}
else
{
dockerClient.buildImageCmd()
.withBaseDirectory(baseDir)
.withDockerfile(dockerFile)
.withTags(Sets.newHashSet(name))
.exec(callback)
.awaitImageId();
}

List<ExposedPort> tcpPorts = new ArrayList<>();
List<PortBinding> portBindings = new ArrayList<>();
Expand Down
7 changes: 6 additions & 1 deletion scripts/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ _sed-in-place() {
rm "$tempFile"
}

_metrics_collector_supported() {
# currently, metrics collector does not work on arm64
[ "$(uname -m)" != "aarch64" ]
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the best way to handle this. Somehow we need to disable the metrics collector for arm64. This appears to be working, but I'm open to suggestions.


if [ "$1" = 'mgmtapi' ]; then
echo "Starting Management API"

Expand All @@ -55,7 +60,7 @@ if [ "$1" = 'mgmtapi' ]; then
# 2. We don't wan't operator or configbuilder to care so much about the version number or
# the fact this jar even exists.

if ! grep -qxF "JVM_OPTS=\"\$JVM_OPTS -javaagent:/opt/mcac-agent/lib/datastax-mcac-agent.jar\"" < /etc/cassandra/cassandra-env.sh ; then
if _metrics_collector_supported && ! grep -qxF "JVM_OPTS=\"\$JVM_OPTS -javaagent:/opt/mcac-agent/lib/datastax-mcac-agent.jar\"" < /etc/cassandra/cassandra-env.sh ; then
# ensure newline at end of file
echo "" >> /etc/cassandra/cassandra-env.sh
echo "JVM_OPTS=\"\$JVM_OPTS -javaagent:/opt/mcac-agent/lib/datastax-mcac-agent.jar\"" >> /etc/cassandra/cassandra-env.sh
Expand Down