containers

153 Topics
"}},"componentScriptGroups({\"componentId\":\"custom.widget.MicrosoftFooter\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageListTabs\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageListTabs-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewInline\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/Pager/PagerLoadMore\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/OverflowNav\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageUnreadCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageViewCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageViewCount-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/kudos/KudosCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/kudos/KudosCount-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRepliesCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1747867729000"}],"cachedText({\"lastModified\":\"1747867729000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1747867729000"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Anonymous","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"MMM dd yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US","es-ES"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1750094418845":{"__typename":"CachedAsset","id":"pages-1750094418845","value":[{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"UserBlogPermissions.Page","type":"COMMUNITY","urlPath":"/c/user-blog-permissions/page","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"AllEvents","type":"CUSTOM","urlPath":"/Events","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"CommunityHub.Page","type":"CUSTOM","urlPath":"/Directory","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1730819800000,"localOverride":null,"page":{"id":"AllBlogs.Page","type":"CUSTOM","urlPath":"/blogs","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1750094418845,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:theme:customTheme1-1750094418256":{"__typename":"CachedAsset","id":"theme:customTheme1-1750094418256","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["default"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"favicon-1730836283320.png","imageLastModified":"1730836286415","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"favicon-1730836271365.png","imageLastModified":"1730836274203","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1300px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_BROWSER","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"3px","borderRadius":"3px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"16px","paddingXHero":"60px","fontStyle":"NORMAL","fontWeight":"700","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-200)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-200)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-200-h), var(--lia-bs-gray-200-s), calc(var(--lia-bs-gray-200-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"LIGHT","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.16)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.12)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-link-color)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","forumColor":"#4099E2","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#148563","blogColor":"#1CBAA0","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#4C6B90","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#FF8000","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#D13A1F","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#333333","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#717171","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0069D4","secondary":"#333333","bodyText":"#1E1E1E","bodyBg":"#FFFFFF","info":"#409AE2","success":"#41C5AE","warning":"#FCC844","danger":"#BC341B","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#D3F5A4","#243A5E"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Segoe UI","fontStyle":"NORMAL","fontWeight":"400","h1FontSize":"34px","h2FontSize":"32px","h3FontSize":"28px","h4FontSize":"24px","h5FontSize":"20px","h6FontSize":"16px","lineHeight":"1.3","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":"","imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"40px","defaultMessageHeaderMarginBottom":"20px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"40px","specialMessageHeaderMarginBottom":"20px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Segoe UI","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.5","fontSizeBase":"16px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"14px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[{"source":"SERVER","name":"Segoe UI","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"},{"style":"NORMAL","weight":"300","__typename":"FontStyleData"},{"style":"NORMAL","weight":"600","__typename":"FontStyleData"},{"style":"NORMAL","weight":"700","__typename":"FontStyleData"},{"style":"ITALIC","weight":"400","__typename":"FontStyleData"}],"assetNames":["SegoeUI-normal-400.woff2","SegoeUI-normal-300.woff2","SegoeUI-normal-600.woff2","SegoeUI-normal-700.woff2","SegoeUI-italic-400.woff2"],"__typename":"CustomFont"},{"source":"SERVER","name":"MWF Fluent Icons","styles":[{"style":"NORMAL","weight":"400","__typename":"FontStyleData"}],"assetNames":["MWFFluentIcons-normal-400.woff2"],"__typename":"CustomFont"}],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1747867729000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1747867729000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/tags/TagPage-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-pages/tags/TagPage-1747867729000","value":{"tagPageTitle":"Tag:\"{tagName}\" | {communityTitle}","tagPageForNodeTitle":"Tag:\"{tagName}\" in \"{title}\" | {communityTitle}","name":"Tags Page","tag":"Tag: {tagName}"},"localOverride":false},"Category:category:Azure":{"__typename":"Category","id":"category:Azure","entityType":"CATEGORY","displayId":"Azure","nodeType":"category","depth":3,"title":"Azure","shortTitle":"Azure","parent":{"__ref":"Category:category:products-services"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","displayId":"top","nodeType":"category","depth":0,"title":"Top"},"Category:category:communities":{"__typename":"Category","id":"category:communities","displayId":"communities","nodeType":"category","depth":1,"parent":{"__ref":"Category:category:top"},"title":"Communities"},"Category:category:products-services":{"__typename":"Category","id":"category:products-services","displayId":"products-services","nodeType":"category","depth":2,"parent":{"__ref":"Category:category:communities"},"title":"Products"},"Blog:board:AppsonAzureBlog":{"__typename":"Blog","id":"board:AppsonAzureBlog","entityType":"BLOG","displayId":"AppsonAzureBlog","nodeType":"board","depth":4,"conversationStyle":"BLOG","title":"Apps on Azure Blog","description":"","avatar":null,"profileSettings":{"__typename":"ProfileSettings","language":null},"parent":{"__ref":"Category:category:Azure"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:gxcuf89792"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:communities"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:products-services"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:Azure"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"boardPolicies":{"__typename":"BoardPolicies","canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}}},"theme":{"__ref":"Theme:customTheme1"},"shortTitle":"Apps on Azure Blog","tagPolicies":{"__typename":"TagPolicies","canSubscribeTagOnNode":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.labels.action.corenode.subscribe_labels.allow.accessDenied","key":"error.lithium.policies.labels.action.corenode.subscribe_labels.allow.accessDenied","args":[]}},"canManageTagDashboard":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.labels.action.corenode.admin_labels.allow.accessDenied","key":"error.lithium.policies.labels.action.corenode.admin_labels.allow.accessDenied","args":[]}}}},"CachedAsset:quilt:o365.prod:pages/tags/TagPage:board:AppsonAzureBlog-1750094416187":{"__typename":"CachedAsset","id":"quilt:o365.prod:pages/tags/TagPage:board:AppsonAzureBlog-1750094416187","value":{"id":"TagPage","container":{"id":"Common","headerProps":{"removeComponents":["community.widget.bannerWidget"],"__typename":"QuiltContainerSectionProps"},"items":[{"id":"tag-header-widget","layout":"ONE_COLUMN","bgColor":"var(--lia-bs-white)","showBorder":"BOTTOM","sectionEditLevel":"LOCKED","columnMap":{"main":[{"id":"tags.widget.TagsHeaderWidget","__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"},{"id":"messages-list-for-tag-widget","layout":"ONE_COLUMN","columnMap":{"main":[{"id":"messages.widget.messageListForNodeByRecentActivityWidget","props":{"viewVariant":{"type":"inline","props":{"useUnreadCount":true,"useViewCount":true,"useAuthorLogin":true,"clampBodyLines":3,"useAvatar":true,"useBoardIcon":false,"useKudosCount":true,"usePreviewMedia":true,"useTags":false,"useNode":true,"useNodeLink":true,"useTextBody":true,"truncateBodyLength":-1,"useBody":true,"useRepliesCount":true,"useSolvedBadge":true,"timeStampType":"conversation.lastPostingActivityTime","useMessageTimeLink":true,"clampSubjectLines":2}},"panelType":"divider","useTitle":false,"hideIfEmpty":false,"pagerVariant":{"type":"loadMore"},"style":"list","showTabs":true,"tabItemMap":{"default":{"mostRecent":true,"mostRecentUserContent":false,"newest":false},"additional":{"mostKudoed":true,"mostViewed":true,"mostReplies":false,"noReplies":false,"noSolutions":false,"solutions":false}}},"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"}],"__typename":"QuiltContainer"},"__typename":"Quilt"},"localOverride":false},"CachedAsset:quiltWrapper:o365.prod:Common:1750094349614":{"__typename":"CachedAsset","id":"quiltWrapper:o365.prod:Common:1750094349614","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"community.widget.navbarWidget","props":{"showUserName":true,"showRegisterLink":true,"useIconLanguagePicker":true,"useLabelLanguagePicker":true,"className":"QuiltComponent_lia-component-edit-mode__0nCcm","links":{"sideLinks":[],"mainLinks":[{"children":[],"linkType":"INTERNAL","id":"gxcuf89792","params":{},"routeName":"CommunityPage"},{"children":[],"linkType":"EXTERNAL","id":"external-link","url":"/Directory","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft365","params":{"categoryId":"microsoft365"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows","params":{"categoryId":"Windows"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"Common-microsoft365-copilot-link","params":{"categoryId":"Microsoft365Copilot"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-teams","params":{"categoryId":"MicrosoftTeams"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-securityand-compliance","params":{"categoryId":"microsoft-security"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"azure","params":{"categoryId":"Azure"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"Common-content_management-link","params":{"categoryId":"Content_Management"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"exchange","params":{"categoryId":"Exchange"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"windows-server","params":{"categoryId":"Windows-Server"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"outlook","params":{"categoryId":"Outlook"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-endpoint-manager","params":{"categoryId":"microsoftintune"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-2","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities","url":"/","target":"BLANK"},{"children":[{"linkType":"INTERNAL","id":"a-i","params":{"categoryId":"AI"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"education-sector","params":{"categoryId":"EducationSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"partner-community","params":{"categoryId":"PartnerCommunity"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"i-t-ops-talk","params":{"categoryId":"ITOpsTalk"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"healthcare-and-life-sciences","params":{"categoryId":"HealthcareAndLifeSciences"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-mechanics","params":{"categoryId":"MicrosoftMechanics"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"public-sector","params":{"categoryId":"PublicSector"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"s-m-b","params":{"categoryId":"MicrosoftforNonprofits"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"io-t","params":{"categoryId":"IoT"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"startupsat-microsoft","params":{"categoryId":"StartupsatMicrosoft"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"driving-adoption","params":{"categoryId":"DrivingAdoption"},"routeName":"CategoryPage"},{"linkType":"EXTERNAL","id":"external-link-1","url":"/Directory","target":"SELF"}],"linkType":"EXTERNAL","id":"communities-1","url":"/","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external","url":"/Blogs","target":"SELF"},{"children":[],"linkType":"EXTERNAL","id":"external-1","url":"/Events","target":"SELF"},{"children":[{"linkType":"INTERNAL","id":"microsoft-learn-1","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"microsoft-learn-blog","params":{"boardId":"MicrosoftLearnBlog","categoryId":"MicrosoftLearn"},"routeName":"BlogBoardPage"},{"linkType":"EXTERNAL","id":"external-10","url":"https://learningroomdirectory.microsoft.com/","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-3","url":"https://docs.microsoft.com/learn/dynamics365/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-4","url":"https://docs.microsoft.com/learn/m365/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-5","url":"https://docs.microsoft.com/learn/topics/sci/?wt.mc_id=techcom_header-webpage-m365","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-6","url":"https://docs.microsoft.com/learn/powerplatform/?wt.mc_id=techcom_header-webpage-powerplatform","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-7","url":"https://docs.microsoft.com/learn/github/?wt.mc_id=techcom_header-webpage-github","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-8","url":"https://docs.microsoft.com/learn/teams/?wt.mc_id=techcom_header-webpage-teams","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-9","url":"https://docs.microsoft.com/learn/dotnet/?wt.mc_id=techcom_header-webpage-dotnet","target":"BLANK"},{"linkType":"EXTERNAL","id":"external-2","url":"https://docs.microsoft.com/learn/azure/?WT.mc_id=techcom_header-webpage-m365","target":"BLANK"}],"linkType":"INTERNAL","id":"microsoft-learn","params":{"categoryId":"MicrosoftLearn"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"community-info-center","params":{"categoryId":"Community-Info-Center"},"routeName":"CategoryPage"}]},"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","controllerHighlightColor":"hsla(30, 100%, 50%)","linkFontWeight":"400","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkBoxShadowHover":"none","linkFontSize":"14px","backgroundOpacity":0.8,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","hamburgerColor":"var(--lia-nav-controller-icon-color)","linkTextBorderBottom":"none","brandLogoHeight":"30px","linkBgHoverColor":"transparent","linkLetterSpacing":"normal","collapseMenuDividerOpacity":0.16,"dropdownPaddingBottom":"15px","paddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"1px solid var(--lia-bs-border-color)","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","collapseMenuDividerBg":"var(--lia-nav-link-color)","linkColor":"var(--lia-bs-body-color)","linkJustifyContent":"flex-start","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","controllerTextColor":"var(--lia-nav-controller-icon-color)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-body-color)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid var(--lia-bs-body-color)","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","linkPaddingX":"10px","linkPaddingY":"5px","paddingTop":"15px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkBgColor":"transparent","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkDropdownPaddingY":"9px","controllerIconColor":"var(--lia-bs-body-color)","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"var(--lia-bs-body-color)"},"showSearchIcon":false,"languagePickerStyle":"iconAndLabel"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"transparent","linkHighlightColor":"var(--lia-bs-primary)","visualEffects":{"showBottomBorder":true},"linkTextColor":"var(--lia-bs-gray-700)"},"__typename":"QuiltComponent"},{"id":"custom.widget.tempStatusBanner","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.HeroBanner","props":{"widgetVisibility":"signedInOrAnonymous","usePageWidth":false,"useTitle":true,"cMax_items":3,"useBackground":false,"title":"","lazyLoad":false,"widgetChooser":"custom.widget.HeroBanner"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.MicrosoftFooter","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1747867729000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:component:custom.widget.tempStatusBanner-en-us-1750094469878":{"__typename":"CachedAsset","id":"component:custom.widget.tempStatusBanner-en-us-1750094469878","value":{"component":{"id":"custom.widget.tempStatusBanner","template":{"id":"tempStatusBanner","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.tempStatusBanner","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.HeroBanner-en-us-1750094469878":{"__typename":"CachedAsset","id":"component:custom.widget.HeroBanner-en-us-1750094469878","value":{"component":{"id":"custom.widget.HeroBanner","template":{"id":"HeroBanner","markupLanguage":"REACT","style":null,"texts":{"searchPlaceholderText":"Search this community","followActionText":"Follow","unfollowActionText":"Following","searchOnHoverText":"Please enter your search term(s) and then press return key to complete a search.","blogs.sidebar.pagetitle":"Latest Blogs | Microsoft Tech Community","followThisNode":"Follow this node","unfollowThisNode":"Unfollow this node"},"defaults":{"config":{"applicablePages":[],"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.HeroBanner","form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":null,"fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[{"id":"max_items","dataType":"NUMBER","list":false,"defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"control":"INPUT","__typename":"PropDefinition"}],"__typename":"ComponentProperties"},"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"},"__typename":"Component","localOverride":false},"globalCss":null,"form":{"fields":[{"id":"widgetChooser","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"title","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useTitle","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"useBackground","validation":null,"noValidation":null,"dataType":"BOOLEAN","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"widgetVisibility","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"moreOptions","validation":null,"noValidation":null,"dataType":"STRING","list":null,"control":null,"defaultValue":null,"label":null,"description":null,"possibleValues":null,"__typename":"FormField"},{"id":"cMax_items","validation":null,"noValidation":null,"dataType":"NUMBER","list":false,"control":"INPUT","defaultValue":"3","label":"Max Items","description":"The maximum number of items to display in the carousel","possibleValues":null,"__typename":"FormField"}],"layout":{"rows":[{"id":"widgetChooserGroup","type":"fieldset","as":null,"items":[{"id":"widgetChooser","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"titleGroup","type":"fieldset","as":null,"items":[{"id":"title","className":null,"__typename":"FormFieldRef"},{"id":"useTitle","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"useBackground","type":"fieldset","as":null,"items":[{"id":"useBackground","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"widgetVisibility","type":"fieldset","as":null,"items":[{"id":"widgetVisibility","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"moreOptionsGroup","type":"fieldset","as":null,"items":[{"id":"moreOptions","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"},{"id":"componentPropsGroup","type":"fieldset","as":null,"items":[{"id":"cMax_items","className":null,"__typename":"FormFieldRef"}],"props":null,"legend":null,"description":null,"className":null,"viewVariant":null,"toggleState":null,"__typename":"FormFieldset"}],"actionButtons":null,"className":"custom_widget_HeroBanner_form","formGroupFieldSeparator":"divider","__typename":"FormLayout"},"__typename":"Form"}},"localOverride":false},"CachedAsset:component:custom.widget.MicrosoftFooter-en-us-1750094469878":{"__typename":"CachedAsset","id":"component:custom.widget.MicrosoftFooter-en-us-1750094469878","value":{"component":{"id":"custom.widget.MicrosoftFooter","template":{"id":"MicrosoftFooter","markupLanguage":"HANDLEBARS","style":".context-uhf {\n min-width: 280px;\n font-size: 15px;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.c-uhff-link {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.c-uhff {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.c-uhff-nav {\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n .c-heading-4 {\n color: #616161;\n word-break: break-word;\n font-size: 15px;\n line-height: 20px;\n padding: 36px 0 4px;\n font-weight: 600;\n }\n .c-uhff-nav-row {\n .c-uhff-nav-group {\n display: block;\n float: left;\n min-height: 1px;\n vertical-align: text-top;\n padding: 0 12px;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 12px;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.c-list.f-bare {\n font-size: 11px;\n line-height: 16px;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 8px 0;\n margin: 0;\n }\n }\n }\n }\n}\n.c-uhff-base {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(1600px + 10%);\n padding: 30px 5% 16px;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.c-uhff-ccpa {\n font-size: 11px;\n line-height: 16px;\n float: left;\n margin: 3px 0;\n }\n a.c-uhff-ccpa:hover {\n text-decoration: underline;\n }\n ul.c-list {\n font-size: 11px;\n line-height: 16px;\n float: right;\n margin: 3px 0;\n color: #616161;\n li {\n padding: 0 24px 4px 0;\n display: inline-block;\n }\n }\n .c-list.f-bare {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 30px 24px 16px;\n }\n}\n\n.social-share {\n position: fixed;\n top: 60%;\n transform: translateY(-50%);\n left: 0;\n z-index: 1000;\n}\n\n.sharing-options {\n list-style: none;\n padding: 0;\n margin: 0;\n display: block;\n flex-direction: column;\n background-color: white;\n width: 50px;\n border-radius: 0px 7px 7px 0px;\n}\n.linkedin-icon {\n border-top-right-radius: 7px;\n}\n.linkedin-icon:hover {\n border-radius: 0;\n}\n\n.social-share-email-image:hover {\n border-radius: 0;\n}\n\n.social-link-footer:hover .linkedin-icon {\n border-radius: 0;\n}\n.social-link-footer:hover .social-share-email-image {\n border-radius: 0;\n}\n\n.social-link-footer img {\n width: 30px;\n height: auto;\n transition: filter 0.3s ease;\n}\n\n.social-share-list {\n width: 50px;\n}\n.social-share-rss-image {\n width: 30px;\n height: auto;\n transition: filter 0.3s ease;\n}\n.sharing-options li {\n width: 50px;\n height: 50px;\n padding: 8px;\n box-sizing: border-box;\n border: 2px solid white; \n display: inline-block;\n text-align: center;\n opacity: 1;\n visibility: visible;\n transition: border 0.3s ease; /* Smooth transition effect */\n border-left: none;\n border-bottom: none; /* Apply bottom border to only last item */\n}\n\n.social-share-list-linkedin {\n background-color: #0474b4;\n border-top-right-radius: 5px; /* Rounded top right corner of first item*/\n}\n.social-share-list-facebook {\n background-color: #3c5c9c;\n}\n.social-share-list-xicon {\n background-color: #000;\n}\n.social-share-list-reddit {\n background-color: #fc4404;\n}\n.social-share-list-bluesky {\n background-color: #f0f2f5;\n}\n.social-share-list-rss {\n background-color: #ec7b1c;\n}\n.social-share-list-mail {\n background-color: #848484; \n border-bottom-right-radius: 5px; /* Rounded bottom right corner of last item*/\n}\n.sharing-options li.social-share-list-mail {\n border-bottom: 2px solid white; /* Add bottom border only to the last item */\n height: 52px; /* Increase last child height to make in align with the hover label */\n}\n.x-icon {\n filter: invert(100%);\n transition: filter 0.3s ease;\n width: 20px !important;\n height: auto;\n padding-top: 5px !important;\n}\n.bluesky-icon {\n filter: invert(20%) sepia(100%) saturate(3000%) hue-rotate(180deg);\n transition: filter 0.3s ease;\n padding-top: 5px !important;\n width: 25px !important;\n}\n\n.share-icon {\n border: 2px solid transparent;\n display: inline-block;\n position: relative;\n}\n\n.sharing-options li:hover {\n border: 2px solid white; \n border-left: none;\n border-bottom: none;\n border-radius: 0px;\n}\n.sharing-options li.social-share-list-mail:hover {\n border-bottom: 2px solid white; /* Add bottom border only to the last item */\n}\n\n.sharing-options li:hover .label {\n opacity: 1;\n visibility: visible;\n border: 2px solid white;\n box-sizing: border-box;\n border-left: none;\n}\n\n.label {\n position: absolute;\n left: 100%;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n color: white;\n border-radius: 0 10 0 10px;\n top: 50%;\n transform: translateY(-50%);\n height: 52px;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 10px 12px 15px 8px;\n border: 2px solid white;\n}\n.linkedin {\n background-color: #0474b4;\n border-top-right-radius: 5px; /* Rounded top right corner of first item*/\n}\n.facebook {\n background-color: #3c5c9c;\n}\n.twitter {\n background-color: black;\n color: white;\n}\n.reddit {\n background-color: #fc4404;\n}\n.mail {\n background-color: #848484;\n border-bottom-right-radius: 5px; /* Rounded bottom right corner of last item*/\n}\n.bluesky {\n background-color: #f0f2f5;\n color: black;\n}\n.rss {\n background-color: #ec7b1c;\n}\n\n@media (max-width: 991px) {\n .social-share {\n display: none;\n }\n}\n","texts":{"New tab":"What's New","New 1":"Surface Laptop Studio 2","New 2":"Surface Laptop Go 3","New 3":"Surface Pro 9","New 4":"Surface Laptop 5","New 5":"Surface Studio 2+","New 6":"Copilot in Windows","New 7":"Microsoft 365","New 8":"Windows 11 apps","Store tab":"Microsoft Store","Store 1":"Account Profile","Store 2":"Download Center","Store 3":"Microsoft Store Support","Store 4":"Returns","Store 5":"Order tracking","Store 6":"Certified Refurbished","Store 7":"Microsoft Store Promise","Store 8":"Flexible Payments","Education tab":"Education","Edu 1":"Microsoft in education","Edu 2":"Devices for education","Edu 3":"Microsoft Teams for Education","Edu 4":"Microsoft 365 Education","Edu 5":"How to buy for your school","Edu 6":"Educator Training and development","Edu 7":"Deals for students and parents","Edu 8":"Azure for students","Business tab":"Business","Bus 1":"Microsoft Cloud","Bus 2":"Microsoft Security","Bus 3":"Dynamics 365","Bus 4":"Microsoft 365","Bus 5":"Microsoft Power Platform","Bus 6":"Microsoft Teams","Bus 7":"Microsoft Industry","Bus 8":"Small Business","Developer tab":"Developer & IT","Dev 1":"Azure","Dev 2":"Developer Center","Dev 3":"Documentation","Dev 4":"Microsoft Learn","Dev 5":"Microsoft Tech Community","Dev 6":"Azure Marketplace","Dev 7":"AppSource","Dev 8":"Visual Studio","Company tab":"Company","Com 1":"Careers","Com 2":"About Microsoft","Com 3":"Company News","Com 4":"Privacy at Microsoft","Com 5":"Investors","Com 6":"Diversity and inclusion","Com 7":"Accessiblity","Com 8":"Sustainibility"},"defaults":{"config":{"applicablePages":[],"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.MicrosoftFooter","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"The Microsoft Footer","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":{"css":".custom_widget_MicrosoftFooter_context-uhf_yuh6w_1 {\n min-width: 17.5rem;\n font-size: 0.9375rem;\n box-sizing: border-box;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n & *,\n & *:before,\n & *:after {\n box-sizing: inherit;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-link_yuh6w_12 {\n color: #616161;\n word-break: break-word;\n text-decoration: none;\n }\n &a:link,\n &a:focus,\n &a:hover,\n &a:active,\n &a:visited {\n text-decoration: none;\n color: inherit;\n }\n & div {\n font-family: 'Segoe UI', SegoeUI, 'Helvetica Neue', Helvetica, Arial, sans-serif;\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff_yuh6w_12 {\n background: #f2f2f2;\n margin: -1.5625;\n width: auto;\n height: auto;\n}\n.custom_widget_MicrosoftFooter_c-uhff-nav_yuh6w_35 {\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 0 5%;\n box-sizing: inherit;\n &:before,\n &:after {\n content: ' ';\n display: table;\n clear: left;\n }\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n .custom_widget_MicrosoftFooter_c-heading-4_yuh6w_49 {\n color: #616161;\n word-break: break-word;\n font-size: 0.9375rem;\n line-height: 1.25rem;\n padding: 2.25rem 0 0.25rem;\n font-weight: 600;\n }\n .custom_widget_MicrosoftFooter_c-uhff-nav-row_yuh6w_57 {\n .custom_widget_MicrosoftFooter_c-uhff-nav-group_yuh6w_58 {\n display: block;\n float: left;\n min-height: 0.0625rem;\n vertical-align: text-top;\n padding: 0 0.75rem;\n width: 100%;\n zoom: 1;\n &:first-child {\n padding-left: 0;\n @media only screen and (max-width: 1083px) {\n padding-left: 0.75rem;\n }\n }\n @media only screen and (min-width: 540px) and (max-width: 1082px) {\n width: 33.33333%;\n }\n @media only screen and (min-width: 1083px) {\n width: 16.6666666667%;\n }\n ul.custom_widget_MicrosoftFooter_c-list_yuh6w_78.custom_widget_MicrosoftFooter_f-bare_yuh6w_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n margin-top: 0;\n margin-bottom: 0;\n padding-left: 0;\n list-style-type: none;\n li {\n word-break: break-word;\n padding: 0.5rem 0;\n margin: 0;\n }\n }\n }\n }\n}\n.custom_widget_MicrosoftFooter_c-uhff-base_yuh6w_94 {\n background: #f2f2f2;\n margin: 0 auto;\n max-width: calc(100rem + 10%);\n padding: 1.875rem 5% 1rem;\n &:before,\n &:after {\n content: ' ';\n display: table;\n }\n &:after {\n clear: both;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_yuh6w_107 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: left;\n margin: 0.1875rem 0;\n }\n a.custom_widget_MicrosoftFooter_c-uhff-ccpa_yuh6w_107:hover {\n text-decoration: underline;\n }\n ul.custom_widget_MicrosoftFooter_c-list_yuh6w_78 {\n font-size: 0.6875rem;\n line-height: 1rem;\n float: right;\n margin: 0.1875rem 0;\n color: #616161;\n li {\n padding: 0 1.5rem 0.25rem 0;\n display: inline-block;\n }\n }\n .custom_widget_MicrosoftFooter_c-list_yuh6w_78.custom_widget_MicrosoftFooter_f-bare_yuh6w_78 {\n padding-left: 0;\n list-style-type: none;\n }\n @media only screen and (max-width: 1083px) {\n display: flex;\n flex-wrap: wrap;\n padding: 1.875rem 1.5rem 1rem;\n }\n}\n.custom_widget_MicrosoftFooter_social-share_yuh6w_138 {\n position: fixed;\n top: 60%;\n transform: translateY(-50%);\n left: 0;\n z-index: 1000;\n}\n.custom_widget_MicrosoftFooter_sharing-options_yuh6w_146 {\n list-style: none;\n padding: 0;\n margin: 0;\n display: block;\n flex-direction: column;\n background-color: white;\n width: 3.125rem;\n border-radius: 0 0.4375rem 0.4375rem 0;\n}\n.custom_widget_MicrosoftFooter_linkedin-icon_yuh6w_156 {\n border-top-right-radius: 7px;\n}\n.custom_widget_MicrosoftFooter_linkedin-icon_yuh6w_156:hover {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-share-email-image_yuh6w_163:hover {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_yuh6w_167:hover .custom_widget_MicrosoftFooter_linkedin-icon_yuh6w_156 {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_yuh6w_167:hover .custom_widget_MicrosoftFooter_social-share-email-image_yuh6w_163 {\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_social-link-footer_yuh6w_167 img {\n width: 1.875rem;\n height: auto;\n transition: filter 0.3s ease;\n}\n.custom_widget_MicrosoftFooter_social-share-list_yuh6w_180 {\n width: 3.125rem;\n}\n.custom_widget_MicrosoftFooter_social-share-rss-image_yuh6w_183 {\n width: 1.875rem;\n height: auto;\n transition: filter 0.3s ease;\n}\n.custom_widget_MicrosoftFooter_sharing-options_yuh6w_146 li {\n width: 3.125rem;\n height: 3.125rem;\n padding: 0.5rem;\n box-sizing: border-box;\n border: 2px solid white; \n display: inline-block;\n text-align: center;\n opacity: 1;\n visibility: visible;\n transition: border 0.3s ease; /* Smooth transition effect */\n border-left: none;\n border-bottom: none; /* Apply bottom border to only last item */\n}\n.custom_widget_MicrosoftFooter_social-share-list-linkedin_yuh6w_203 {\n background-color: #0474b4;\n border-top-right-radius: 5px; /* Rounded top right corner of first item*/\n}\n.custom_widget_MicrosoftFooter_social-share-list-facebook_yuh6w_207 {\n background-color: #3c5c9c;\n}\n.custom_widget_MicrosoftFooter_social-share-list-xicon_yuh6w_210 {\n background-color: #000;\n}\n.custom_widget_MicrosoftFooter_social-share-list-reddit_yuh6w_213 {\n background-color: #fc4404;\n}\n.custom_widget_MicrosoftFooter_social-share-list-bluesky_yuh6w_216 {\n background-color: #f0f2f5;\n}\n.custom_widget_MicrosoftFooter_social-share-list-rss_yuh6w_219 {\n background-color: #ec7b1c;\n}\n.custom_widget_MicrosoftFooter_social-share-list-mail_yuh6w_222 {\n background-color: #848484; \n border-bottom-right-radius: 5px; /* Rounded bottom right corner of last item*/\n}\n.custom_widget_MicrosoftFooter_sharing-options_yuh6w_146 li.custom_widget_MicrosoftFooter_social-share-list-mail_yuh6w_222 {\n border-bottom: 2px solid white; /* Add bottom border only to the last item */\n height: 3.25rem; /* Increase last child height to make in align with the hover label */\n}\n.custom_widget_MicrosoftFooter_x-icon_yuh6w_230 {\n filter: invert(100%);\n transition: filter 0.3s ease;\n width: 1.25rem !important;\n height: auto;\n padding-top: 0.3125rem !important;\n}\n.custom_widget_MicrosoftFooter_bluesky-icon_yuh6w_237 {\n filter: invert(20%) sepia(100%) saturate(3000%) hue-rotate(180deg);\n transition: filter 0.3s ease;\n padding-top: 0.3125rem !important;\n width: 1.5625rem !important;\n}\n.custom_widget_MicrosoftFooter_share-icon_yuh6w_244 {\n border: 2px solid transparent;\n display: inline-block;\n position: relative;\n}\n.custom_widget_MicrosoftFooter_sharing-options_yuh6w_146 li:hover {\n border: 2px solid white; \n border-left: none;\n border-bottom: none;\n border-radius: 0;\n}\n.custom_widget_MicrosoftFooter_sharing-options_yuh6w_146 li.custom_widget_MicrosoftFooter_social-share-list-mail_yuh6w_222:hover {\n border-bottom: 2px solid white; /* Add bottom border only to the last item */\n}\n.custom_widget_MicrosoftFooter_sharing-options_yuh6w_146 li:hover .custom_widget_MicrosoftFooter_label_yuh6w_260 {\n opacity: 1;\n visibility: visible;\n border: 2px solid white;\n box-sizing: border-box;\n border-left: none;\n}\n.custom_widget_MicrosoftFooter_label_yuh6w_260 {\n position: absolute;\n left: 100%;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: all 0.2s ease;\n color: white;\n border-radius: 0 10 0 0.625rem;\n top: 50%;\n transform: translateY(-50%);\n height: 3.25rem;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.625rem 0.75rem 0.9375rem 0.5rem;\n border: 2px solid white;\n}\n.custom_widget_MicrosoftFooter_linkedin_yuh6w_156 {\n background-color: #0474b4;\n border-top-right-radius: 5px; /* Rounded top right corner of first item*/\n}\n.custom_widget_MicrosoftFooter_facebook_yuh6w_290 {\n background-color: #3c5c9c;\n}\n.custom_widget_MicrosoftFooter_twitter_yuh6w_293 {\n background-color: black;\n color: white;\n}\n.custom_widget_MicrosoftFooter_reddit_yuh6w_297 {\n background-color: #fc4404;\n}\n.custom_widget_MicrosoftFooter_mail_yuh6w_300 {\n background-color: #848484;\n border-bottom-right-radius: 5px; /* Rounded bottom right corner of last item*/\n}\n.custom_widget_MicrosoftFooter_bluesky_yuh6w_237 {\n background-color: #f0f2f5;\n color: black;\n}\n.custom_widget_MicrosoftFooter_rss_yuh6w_308 {\n background-color: #ec7b1c;\n}\n@media (max-width: 991px) {\n .custom_widget_MicrosoftFooter_social-share_yuh6w_138 {\n display: none;\n }\n}\n","tokens":{"context-uhf":"custom_widget_MicrosoftFooter_context-uhf_yuh6w_1","c-uhff-link":"custom_widget_MicrosoftFooter_c-uhff-link_yuh6w_12","c-uhff":"custom_widget_MicrosoftFooter_c-uhff_yuh6w_12","c-uhff-nav":"custom_widget_MicrosoftFooter_c-uhff-nav_yuh6w_35","c-heading-4":"custom_widget_MicrosoftFooter_c-heading-4_yuh6w_49","c-uhff-nav-row":"custom_widget_MicrosoftFooter_c-uhff-nav-row_yuh6w_57","c-uhff-nav-group":"custom_widget_MicrosoftFooter_c-uhff-nav-group_yuh6w_58","c-list":"custom_widget_MicrosoftFooter_c-list_yuh6w_78","f-bare":"custom_widget_MicrosoftFooter_f-bare_yuh6w_78","c-uhff-base":"custom_widget_MicrosoftFooter_c-uhff-base_yuh6w_94","c-uhff-ccpa":"custom_widget_MicrosoftFooter_c-uhff-ccpa_yuh6w_107","social-share":"custom_widget_MicrosoftFooter_social-share_yuh6w_138","sharing-options":"custom_widget_MicrosoftFooter_sharing-options_yuh6w_146","linkedin-icon":"custom_widget_MicrosoftFooter_linkedin-icon_yuh6w_156","social-share-email-image":"custom_widget_MicrosoftFooter_social-share-email-image_yuh6w_163","social-link-footer":"custom_widget_MicrosoftFooter_social-link-footer_yuh6w_167","social-share-list":"custom_widget_MicrosoftFooter_social-share-list_yuh6w_180","social-share-rss-image":"custom_widget_MicrosoftFooter_social-share-rss-image_yuh6w_183","social-share-list-linkedin":"custom_widget_MicrosoftFooter_social-share-list-linkedin_yuh6w_203","social-share-list-facebook":"custom_widget_MicrosoftFooter_social-share-list-facebook_yuh6w_207","social-share-list-xicon":"custom_widget_MicrosoftFooter_social-share-list-xicon_yuh6w_210","social-share-list-reddit":"custom_widget_MicrosoftFooter_social-share-list-reddit_yuh6w_213","social-share-list-bluesky":"custom_widget_MicrosoftFooter_social-share-list-bluesky_yuh6w_216","social-share-list-rss":"custom_widget_MicrosoftFooter_social-share-list-rss_yuh6w_219","social-share-list-mail":"custom_widget_MicrosoftFooter_social-share-list-mail_yuh6w_222","x-icon":"custom_widget_MicrosoftFooter_x-icon_yuh6w_230","bluesky-icon":"custom_widget_MicrosoftFooter_bluesky-icon_yuh6w_237","share-icon":"custom_widget_MicrosoftFooter_share-icon_yuh6w_244","label":"custom_widget_MicrosoftFooter_label_yuh6w_260","linkedin":"custom_widget_MicrosoftFooter_linkedin_yuh6w_156","facebook":"custom_widget_MicrosoftFooter_facebook_yuh6w_290","twitter":"custom_widget_MicrosoftFooter_twitter_yuh6w_293","reddit":"custom_widget_MicrosoftFooter_reddit_yuh6w_297","mail":"custom_widget_MicrosoftFooter_mail_yuh6w_300","bluesky":"custom_widget_MicrosoftFooter_bluesky_yuh6w_237","rss":"custom_widget_MicrosoftFooter_rss_yuh6w_308"}},"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1747867729000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagsHeaderWidget-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagsHeaderWidget-1747867729000","value":{"tag":"{tagName}","topicsCount":"{count} {count, plural, one {Topic} other {Topics}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1747867729000","value":{"title@userScope:other":"Recent Content","title@userScope:self":"Contributions","title@board:FORUM@userScope:other":"Recent Discussions","title@board:BLOG@userScope:other":"Recent Blogs","emptyDescription":"No content to show","MessageListForNodeByRecentActivityWidgetEditor.nodeScope.label":"Scope","title@instance:1722894000155":"Recent Discussions","title@instance:1727367112619":"Recent Blog Articles","title@instance:1727367069748":"Recent Discussions","title@instance:1727366213114":"Latest Discussions","title@instance:1727899609720":"","title@instance:1727363308925":"Latest Discussions","title@instance:1737115580352":"Latest Articles","title@instance:1720453418992":"Recent Discssions","title@instance:1727365950181":"Latest Blog Articles","title@instance:bmDPnI":"Latest Blog Articles","title@instance:IiDDJZ":"Latest Blog Articles","title@instance:1721244347979":"Latest blog posts","title@instance:1728383752171":"Related Content","title@instance:1722893956545":"Latest Skilling Resources","title@instance:dhcgCU":"Latest Discussions"},"localOverride":false},"Category:category:Exchange":{"__typename":"Category","id":"category:Exchange","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Outlook":{"__typename":"Category","id":"category:Outlook","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Community-Info-Center":{"__typename":"Category","id":"category:Community-Info-Center","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:EducationSector":{"__typename":"Category","id":"category:EducationSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:DrivingAdoption":{"__typename":"Category","id":"category:DrivingAdoption","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows-Server":{"__typename":"Category","id":"category:Windows-Server","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftTeams":{"__typename":"Category","id":"category:MicrosoftTeams","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PublicSector":{"__typename":"Category","id":"category:PublicSector","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft365":{"__typename":"Category","id":"category:microsoft365","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:IoT":{"__typename":"Category","id":"category:IoT","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:HealthcareAndLifeSciences":{"__typename":"Category","id":"category:HealthcareAndLifeSciences","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:ITOpsTalk":{"__typename":"Category","id":"category:ITOpsTalk","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftLearn":{"__typename":"Category","id":"category:MicrosoftLearn","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Blog:board:MicrosoftLearnBlog":{"__typename":"Blog","id":"board:MicrosoftLearnBlog","blogPolicies":{"__typename":"BlogPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:AI":{"__typename":"Category","id":"category:AI","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftMechanics":{"__typename":"Category","id":"category:MicrosoftMechanics","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:MicrosoftforNonprofits":{"__typename":"Category","id":"category:MicrosoftforNonprofits","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:StartupsatMicrosoft":{"__typename":"Category","id":"category:StartupsatMicrosoft","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:PartnerCommunity":{"__typename":"Category","id":"category:PartnerCommunity","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Microsoft365Copilot":{"__typename":"Category","id":"category:Microsoft365Copilot","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Windows":{"__typename":"Category","id":"category:Windows","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Content_Management":{"__typename":"Category","id":"category:Content_Management","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoft-security":{"__typename":"Category","id":"category:microsoft-security","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:microsoftintune":{"__typename":"Category","id":"category:microsoftintune","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Conversation:conversation:2867265":{"__typename":"Conversation","id":"conversation:2867265","topic":{"__typename":"BlogTopicMessage","uid":2867265},"lastPostingActivityTime":"2021-12-19T04:49:48.941-08:00","solved":false},"User:user:665873":{"__typename":"User","uid":665873,"login":"DariaGrigoriu","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS02NjU4NzMtMTkxNTg1aUYzQTJBQTVENUMxNDE3MUU"},"id":"user:665873"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMxODg1MmlDN0YxNjk2QUEyMDE4OTU5?revision=14\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMxODg1MmlDN0YxNjk2QUEyMDE4OTU5?revision=14","title":"Blog.png","associationType":"TEASER","width":538,"height":300,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3MWk4REFFNzAwMjI3MDdBM0Y0?revision=14\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3MWk4REFFNzAwMjI3MDdBM0Y0?revision=14","title":"create-res.png","associationType":"BODY","width":1230,"height":588,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMxODg0NmkxQ0NCQUZDQ0VCQ0IzMDlG?revision=14\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMxODg0NmkxQ0NCQUZDQ0VCQ0IzMDlG?revision=14","title":"ContaineAppsBlogPost.gif","associationType":"BODY","width":1920,"height":996,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3NGlBMkY4QTc0OUQ3NzY2NTRE?revision=14\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3NGlBMkY4QTc0OUQ3NzY2NTRE?revision=14","title":"scale-res.png","associationType":"BODY","width":1230,"height":603,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY0NGk0OUMzOUYwQjgxRkI2Njk1?revision=14\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY0NGk0OUMzOUYwQjgxRkI2Njk1?revision=14","title":"dapr.png","associationType":"BODY","width":702,"height":624,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3NmkzOEFFN0Q1NERDQzU1RDY1?revision=14\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3NmkzOEFFN0Q1NERDQzU1RDY1?revision=14","title":"lifecycle-res.png","associationType":"BODY","width":1230,"height":585,"altText":null},"BlogTopicMessage:message:2867265":{"__typename":"BlogTopicMessage","subject":"Introducing Azure Container Apps: a serverless container service for running modern apps at scale","conversation":{"__ref":"Conversation:conversation:2867265"},"id":"message:2867265","revisionNum":14,"uid":2867265,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:665873"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" \n Announcing Azure Container Apps—a serverless container service for building and deploying modern apps at scale, built on open-source technology. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":103400},"postTime":"2021-11-02T08:00:00.970-07:00","lastPublishTime":"2021-11-02T09:58:22.431-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" The fast pace of innovation today requires businesses to focus on differentiated business logic and high velocity delivery to maximize impact. Business logic is often encapsulated in modern cloud native applications represented as microservices with multiple application components that are independently developed and interconnected. Many cloud hosting options for microservices and containerized applications require infrastructure management and orchestration that can increase solution complexity, overall cost, and time to market. \n   \n At Ignite, we announced Azure Container Apps, a serverless application centric hosting service where users do not see or manage any underlying VMs, orchestrators, or other cloud infrastructure. Azure Container Apps enables executing application code packaged in any container and is unopinionated about runtime or programming model. Applications can scale in response to HTTP requests, events (e.g. storage queue messages, Kafka topics, etc.), or simply run as always-on background jobs. Azure Container Apps addresses specific requirements for microservices including encrypted service to service communication and the independent versioning and scaling of services. \n   \n Azure Container Apps is built on the foundation of powerful open-source technology in the Kubernetes ecosystem . The open-source centric approach enables a path for teams to build microservices without having to overcome the concept and operational overhead of working with Kubernetes directly and enables continued application portability by leveraging open standards and APIs. Behind the scenes, every application runs on Azure Kubernetes Service, with Kubernetes Event Driven Autoscaling (KEDA), Distributed Application Runtime (Dapr), and Envoy deeply integrated in the hosting service. \n   \n Getting started with Azure Container Apps \n Multiple individual Container Apps can be deployed to a single Container Apps environment, which acts as an isolation and observability boundary between a group of Container Apps. Container Apps deployed to the same environment write logs to the same Log Analytics workspace. This structure enables easy communication between microservices that compose the overall solution. Additionally, multiple containers can be deployed to the same container app and in that case, they’ll be deployed and scaled together as a single unit or pod of containers. To get started with Azure Container Apps see Quickstart: Deploy an HTTP application to Azure Container Apps. \n   \n \n You can use the Azure CLI to create and manage Container Apps. \n   \n \n   \n Horizontal autoscaling and scale triggers \n Azure Container Apps manages horizontal autoscaling through a set of declarative scaling rules. By default, Azure Container Apps scale to zero and pause billing when not in use. As a Container App scales out, new instances of the Container App are created on-demand. Container Apps supports many scale triggers including HTTP and event-based triggers using Kubernetes Event Driven Autoscaling (KEDA). KEDA is a rich autoscaler with many event scaler options continuously contributed by the community. For more information about supported scale triggers, see KEDA Scalers. See How-to – Set scaling rules in Azure Container Apps for more details. \n   \n \n   \n Making microservices development easier with Distributed Application Runtime (Dapr) \n Dapr is an open-source event-driven runtime that codifies best practices for building portable microservice applications into independent platform agnostic building blocks using the development language and framework of your choice. Azure Container Apps offers a fully managed version of the Dapr APIs. With Dapr for Azure Container Apps, sidecars can be enabled to run next to your application instances and provide a rich set of capabilities and productivity gains. You can use the following Dapr APIs: Service to Service calls, Pub/Sub, Event Bindings, State Stores, and Actors. See Tutorial – Use Dapr in Azure Container Apps for more details. \n   \n \n App lifecycle management \n Azure Container Apps streamlines the application lifecycle management by supporting multiple revisions to manage application versions, enabling traffic splitting and balancing across application versions, securing application secrets, connecting different applications, and delivering integrated monitoring via Log Analytics. See Concepts - Application lifecycle management in Azure Container Apps for more details. \n   \n \n Partner feedback \n \"Many of our users want to package up their microservices and apps in containers, have them scale with demand and not have to worry about managing an underlying cluster,\" said Luke Hoban, CTO of Pulumi. \"We're excited to announce launch day support for Azure Container Apps - so cloud engineers everywhere can define, deploy and manage container apps using their favorite programming languages.\". \n   \n We’re looking forward to the applications you will build with Azure Container Apps! To learn more about Azure Container Apps visit the Getting Started guide on Microsoft Docs and make sure to watch Jeff Hollan do a demo during the Innovate with cloud-native apps and open source on Azure session at Microsoft Ignite, happening tomorrow November 3 rd , 2021. \n   \n Learn more about pricing details by heading over to the Azure Container Apps pricing page, reach us directly via our GitHub microsoft/azure-container-apps repo, and deploy example application at Azure-Samples/container-apps-store-api-microservice. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"5666","kudosSumWeight":9,"repliesCount":5,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMxODg1MmlDN0YxNjk2QUEyMDE4OTU5?revision=14\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3MWk4REFFNzAwMjI3MDdBM0Y0?revision=14\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMxODg0NmkxQ0NCQUZDQ0VCQ0IzMDlG?revision=14\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3NGlBMkY4QTc0OUQ3NzY2NTRE?revision=14\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY0NGk0OUMzOUYwQjgxRkI2Njk1?revision=14\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3MjY1LTMyMTY3NmkzOEFFN0Q1NERDQzU1RDY1?revision=14\"}"}}],"totalCount":6,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:4080165":{"__typename":"Conversation","id":"conversation:4080165","topic":{"__typename":"BlogTopicMessage","uid":4080165},"lastPostingActivityTime":"2024-03-27T12:21:30.744-07:00","solved":false},"User:user:2015652":{"__typename":"User","uid":2015652,"login":"mpgraven","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/m_assets/avatars/default/avatar-11.svg?time=0"},"id":"user:2015652"},"BlogTopicMessage:message:4080165":{"__typename":"BlogTopicMessage","subject":"March 2024: Exploring open source at Microsoft, and other highlights for developers","conversation":{"__ref":"Conversation:conversation:4080165"},"id":"message:4080165","revisionNum":3,"uid":4080165,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:2015652"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Explore some of the open-source projects at Microsoft and resources that will help you start contributing to and managing your own open-source projects. And learn about other news and highlights for developers from around Microsoft. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":51400},"postTime":"2024-03-08T14:38:47.518-08:00","lastPublishTime":"2024-03-08T14:38:47.518-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Microsoft has developed a strong open source program over the past decade. Many of our tools and approaches are available for you to learn from and contribute to. This blog post explores some of the open-source projects at Microsoft and resources that will help you start contributing to and managing your own open-source projects. To learn more about Open Source at Microsoft, visit opensource.microsoft.com.   \n   \n .NET is open source  Did you know .NET is open source? .NET is open source and cross-platform, and it’s maintained by Microsoft and the .NET community. Check it out on GitHub.    \n Microsoft JDConf 2024  Get ready for JDConf 2024—a free virtual event for Java developers. Explore the latest in tooling, architecture, cloud integration, frameworks, and AI. It all happens online March 27-28 and will include sessions on OpenJDK, OpenTelemetry, and Java development with Visual Studio Code. Learn more and register now.    \n Getting started with the Fluent UI Blazor library  The Fluent UI Blazor library is an open-source set of Blazor components used for building applications that have a Fluent design. Watch this Open at Microsoft episode for an overview and find out how to get started with the Fluent UI Blazor library.  \n Generative AI for Beginners  Want to build your own GenAI application? The free Generative AI for Beginners course on GitHub is the perfect place to start. Work through 18 in-depth lessons and learn everything from setting up your environment to using open-source models available on Hugging Face.     \n Reactor series: GenAI for software developers  Step into the future of software development with the Reactor series. GenAI for Software Developers explores cutting-edge AI tools and techniques for developers, revolutionizing the way you build and deploy applications. Register today and elevate your coding skills.  \n How to get GraphQL endpoints with Data API Builder   The Open at Microsoft show takes a look at using Data API Builder to easily create Graph QL endpoints. See how you can use this no-code solution to quickly enable advanced—and efficient—data interactions.    \n Microsoft Graph Toolkit v4.0 is now generally available  Microsoft Graph Toolkit v4.0 is now available. Learn about its new features, bug fixes, and improvements to the developer experience.    \n Customize Dev Containers in VS Code with Dockerfiles and Docker Compose  Dev containers offer a convenient way to deliver consistent and reproducible environments. Follow along with this video demo to customize your dev containers using Dockerfiles and Docker Compose.  \n   \n   \n Other news and highlights for developers   \n AI Show: LLM Evaluations in Azure AI Studio  Don’t deploy your LLM application without testing it first! Watch the AI Show to see how to use Azure AI Studio to evaluate your app’s performance and ensure it’s ready to go live. Watch now.    \n Use OpenAI Assistants API to build your own cooking advisor bot on Teams  Find out how to build an AI assistant right into your app using the new OpenAI Assistants API. Learn about the open playground for experimenting and watch a step-by-step demo for creating a cooking assistant that will suggest recipes based on what’s in your fridge.    \n What’s new in Teams Toolkit for Visual Studio 17.9  What’s new in Teams Toolkit for Visual Studio? Get an overview of new tools and capabilities for .NET developers building apps for Microsoft Teams.   \n Embed a custom webpage in Teams  Find out how to share a custom web page, such as a dashboard or portal, inside a Teams app. It’s easier than you might think. This short video shows how to do this using Teams Toolkit for Visual Studio and Blazor.    \n Build your own assistant for Microsoft Teams  Creating your own assistant app is super easy. Learn how in under 3 minutes! Watch a demo using the OpenAI Assistants, Teams AI Library, and the new AI Assistant Bot template in VS Code.  \n Build your custom copilot with your data on Teams featuring an AI dragon  Build your own copilot for Microsoft Teams in minutes. Watch this video to see how in this demo that builds an AI Dragon that will take your team on a cyber role-playing adventure.   \n Microsoft Mesh: Now available for creating innovative multi-user 3D experiences   Microsoft Mesh is now generally available, providing an immersive 3D experience for the virtual workplace. Get an overview of Microsoft Mesh and find out how to start building your own custom experiences.  \n Global AI Bootcamp 2024  Global AI Bootcamp is a worldwide annual event that runs throughout the month of March for developers and AI enthusiasts. Learn about AI through workshops, sessions, and discussions. Find an in-person bootcamp event near you.   \n C# Dev Kit for Visual Studio Code  Learn how to use the C# Dev Kit for Visual Studio Code. Get details and download the C# Dev Kit from the Visual Studio Marketplace.    \n Visual Studio Code: C# and .NET development for beginners   Have questions about Visual Studio Code and C# Dev Kit? Watch the C# and .NET Development in VS Code for Beginners series and start writing C# applications in VS Code.    \n Python Data Science Day 2024: Unleashing the Power of Python in Data Analysis  Celebrate Pi Day (3.14) with a journey into data science with Python. Set for March 14, Python Data Science Day is an online event for developers, data scientists, students, and researchers who want to explore modern solutions for data pipelines and complex queries.  \n Use GitHub Copilot for your Python coding  Discover a better way to code in Python. Check out this free Microsoft Learn module on how GitHub Copilot provides suggestions while you code in Python.  \n Remote development with Visual Studio Code  Find out how to tap into more powerful hardware and develop on different platforms from your local machine. Check out this Microsoft Learn path to explore tools in VS Code for remote development setups and discover tips for personalizing your own remote dev workflow.  \n Using GitHub Copilot with JavaScript  Use GitHub Copilot while you work with JavaScript. This Microsoft Learn module will tell you everything you need to know to get started with this AI pair programmer.   \n Get to know GitHub Copilot in VS Code and be more productive  Get to know GitHub Copilot in VS Code and find out how to use it. Watch this video to see how incredibly easy it is to start working with GitHub Copilot…Just start coding and watch the AI go to work.   \n Designing for Trust  Learn how to design trustworthy experiences in the world of AI. Watch a demo of an AI prompt injection attack and learn about setting up guardrails to protect the system.   \n Use Visual Studio for modern development  Want to learn more about using Visual Studio to develop and test apps. Start here. In this free learning path, you’ll dig into key features for debugging, editing, and publishing your apps.    \n GitHub Copilot fundamentals - Understand the AI pair programmer  Improve developer productivity and foster innovation with GitHub Copilot. Explore the fundamentals of GitHub Copilot in this free training path from Microsoft Learn.  \n Microsoft, GitHub, and DX release new research into the business ROI of investing in Developer Experience   Investing in the developer experience has many benefits and improves business outcomes. Dive into our groundbreaking research (with data from more than 2000 developers at companies around the world) to discover what your business can gain with better DevEx.   ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"8048","kudosSumWeight":0,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:3942438":{"__typename":"Conversation","id":"conversation:3942438","topic":{"__typename":"BlogTopicMessage","uid":3942438},"lastPostingActivityTime":"2024-02-26T08:37:26.900-08:00","solved":false},"BlogTopicMessage:message:3942438":{"__typename":"BlogTopicMessage","subject":"Developer productivity: security, testing, coding, AI","conversation":{"__ref":"Conversation:conversation:3942438"},"id":"message:3942438","revisionNum":1,"uid":3942438,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:2015652"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Explore tools and resources that will help improve developer productivity.  ","introduction":"","metrics":{"__typename":"MessageMetrics","views":47531},"postTime":"2023-10-02T11:44:09.192-07:00","lastPublishTime":"2023-10-02T11:44:09.192-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" This month, we’re highlighting tools and resources that help improve developer productivity. Discover how to add security to your development workflow, learn about tools to streamline testing, explore enhancements that will help you code faster, and learn new techniques for working with generative AI.  \n   \n Now available: GitHub Advanced Security for Azure DevOps   Discover a new way to automate security checks in the developer workflow. GitHub Advanced Security for Azure DevOps is now available, letting you enable code scanning, secret scanning (to block secrets from being pushed to repos), and dependency scanning.   \n   \n IntelliTest simplifies writing and maintaining unit tests   Automate testing and find bugs earlier in development. The latest IntelliTest preview makes it easier to write and maintain unit tests with high code coverage. Available in Visual Studio Enterprise, IntelliTest supports projects that target .NET 6.    \n   \n Get started with Dev Containers in Visual Studio Code   Boost your coding productivity and save time configuring development environments. Watch this demo to learn how to effortlessly set up and use dev containers in Visual Studio Code.   \n   \n Performance improvements in .NET 8    Curious how .NET 8 improves performance? Take a deep-dive look into numerous changes and performance improvements in the upcoming release of .NET.   \n   \n Learn Live: DevOps and Deconstruct the E2E Workflow for Testing and Deploy  Learn how to test and deploy serverless, intelligent apps to Azure. Watch the session live on October 5 and then on demand to explore the Azure Developer CLI and Playwright.    • Get details and watch the session    • Visit the Learn Collection to explore more resources  \n   \n Microsoft Teams: Tools and SDKs  Did you know Microsoft provides a comprehensive platform for creating, testing, and publishing Microsoft Teams apps. Explore the docs to learn about the tools and SDKs available for building Teams apps.   \n   \n Microsoft 365: Adaptive Card-based Loop components are now in preview  Adaptive Card-based Loop components (now in preview) deliver live, actionable data that stays in sync and can be used across Microsoft 365 apps. Find out how to build your first set of Adaptive Card-based Loop components and try the preview.    \n   \n Visual Studio Video Miniseries: Tea & Technology  Journey into the heart of Visual Studio. Watch this new 7-episode series for in-depth interviews with the product managers helping drive innovation in Visual Studio.    \n   \n New React TypeScript SPA templates and more  The latest Visual Studio preview includes new React TypeScript SPA templates for a better project creation experience. Get details and learn about the benefits. Check it out if you build React TypeScript web applications with ASP.NET as the back end.    \n   \n Demystifying retrieval augmented generation with .NET  Learn how to create an intelligent chat application by building one from the ground up with .NET and Microsoft Semantic Kernel. This blog post guides you through the entire process, complete with all the code samples you’ll need.    \n   \n Generative AI and prompting 101  Watch an overview of Generative AI and learn techniques for crafting prompts that will take your results to a new level. Discover how prompt engineering is transforming how we work and interact with technology.    \n   \n On demand: Resilient App series  Can your apps handle a surge of users and keep transactions flowing? Watch our 7-part Resilient Apps series on demand at Microsoft Reactor to learn practical techniques, optimize performance, and use automated testing.      \n   \n A quick look at easy port forwarding in Visual Studio Code  Watch a quick demo of port forwarding in Visual Studio Code. And read about port forwarding in the user guide.    • Read more     • Watch now    \n   \n Elevate debugging with auto-decompilation and external sources  With Visual Studio 17.7, the debugger took a significant leap forward. Learn about auto-decompilation for .NET libraries and find out how it streamlines external code debugging in Visual Studio.   \n   \n Events and other highlights  \n Announcing: Microsoft Copilot, your everyday AI companion    Get details about the new Microsoft Copilot, a general AI companion that will seamlessly help you get more done. Learn about the newest AI and copilot innovations from Microsoft and find out how to try them yourself.   \n   \n Python in Excel: Combining the power of Python and the flexibility of Excel   Use Python natively in Excel for an even more powerful way to analyze data. Check out this blog post for an overview of the new Python in Excel preview and discover how to use Python while taking advantage of familiar Excel tools, such as formulas, charts, and PivotTables.    \n   \n Data suggests Microsoft 365 Certification increases app adoption rates  Want to increase adoption of your apps? Recent data shows enterprise customers consider Microsoft 365 Certified apps before non-certified apps on average 90% of the time. Learn more about Microsoft 365 Certification.    \n   \n .NET Conf 2023  Save the date for .NET Conf 2023. Join this free digital event November 14–16, 2023 to watch live sessions, get answers straight from .NET experts, and get ready for the official launch of .NET 8.  \n   \n Microsoft Ignite  Register for Microsoft Ignite and join us November 14–17, 2023 to explore the latest innovations, learn from experts, and develop new skills. The Microsoft Ignite event is available in-person and online, making it easy to be a part of the experience.       ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"6141","kudosSumWeight":3,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:3096932":{"__typename":"Conversation","id":"conversation:3096932","topic":{"__typename":"BlogTopicMessage","uid":3096932},"lastPostingActivityTime":"2023-07-16T02:12:50.727-07:00","solved":false},"User:user:296868":{"__typename":"User","uid":296868,"login":"kendallroden","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS0yOTY4NjgtMzQ0NzU4aUJGNTg4NTg0MkE5RkM5MEU"},"id":"user:296868"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5Mmk4NzI0NUNBQzYyQUQ0QkYx?revision=9\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5Mmk4NzI0NUNBQzYyQUQ0QkYx?revision=9","title":"kendallroden_1-1643689866795.png","associationType":"BODY","width":1431,"height":655,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5MWlBMjdEOUI3MzIzRjMyMkMx?revision=9\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5MWlBMjdEOUI3MzIzRjMyMkMx?revision=9","title":"kendallroden_0-1643689866751.png","associationType":"BODY","width":1431,"height":655,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDEwMGk5Q0U3REQ2N0I4OUNFMUY1?revision=9\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDEwMGk5Q0U3REQ2N0I4OUNFMUY1?revision=9","title":"VNET.gif","associationType":"BODY","width":1728,"height":1080,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5OGkxQTlGNTUyRDY0MUI4QjZF?revision=9\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5OGkxQTlGNTUyRDY0MUI4QjZF?revision=9","title":"privatedns.gif","associationType":"BODY","width":1728,"height":1080,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5NGlENkY5RUMwMTdFODMyRDgy?revision=9\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5NGlENkY5RUMwMTdFODMyRDgy?revision=9","title":"kendallroden_5-1643689867190.png","associationType":"BODY","width":1480,"height":570,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDEwMmk2ODEyRkJDRUQ3ODZCRkFB?revision=9\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDEwMmk2ODEyRkJDRUQ3ODZCRkFB?revision=9","title":"Screen Shot 2022-01-31 at 8.28.13 PM.png","associationType":"BODY","width":1526,"height":572,"altText":null},"BlogTopicMessage:message:3096932":{"__typename":"BlogTopicMessage","subject":"Azure Container Apps Virtual Network Integration","conversation":{"__ref":"Conversation:conversation:3096932"},"id":"message:3096932","revisionNum":9,"uid":3096932,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:296868"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Today, we are excited to announce that Azure Container Apps can be deployed into a custom Azure Virtual Network (VNet)! With the release of the Azure Container Apps BYO VNet capability, customers can now configure both inbound and outbound VNet integration for their Azure Container Apps environment. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":45499},"postTime":"2022-02-02T10:51:48.427-08:00","lastPublishTime":"2022-09-02T15:14:58.178-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":"   \n Azure Container Apps Virtual Network Integration release announcement \n   \n At Ignite, we announced Azure Container Apps, a serverless application-centric hosting service that enables users to quickly deploy containerized applications and microservices to Azure without the need to configure and manage underlying infrastructure resources or container orchestrators. Azure Container Apps runs on  Azure Kubernetes Service, and includes several open-source projects: Kubernetes Event Driven Autoscaling (KEDA), Distributed Application Runtime (Dapr), and Envoy. This open-source foundation enables teams to build and run portable applications powered by Kubernetes and open standards without the operational overhead and management complexity of working with the platform directly. \n   \n Since its preview release, the Azure Container Apps service has continued evolving to address customer needs and respond to customer feedback.  One point of focused investment has been addressing asks related to network isolation. For security and compliance reasons, many enterprise customers require isolation to ensure internal, mission critical applications are inaccessible from the public internet. In addition, customers typically have existing cloud resources like databases, queues, file shares, etc. that an application needs to integrate with over this internal, private network. Today, we are excited to announce that Azure Container Apps can be deployed into your custom Azure Virtual Network! In the remainder of this blog, we will walk through configuring inbound and outbound virtual network integration for an Azure Container Apps environment and subsequently deploying Container Apps to the running environment. \n   \n Configure Virtual Network for an Azure Container Apps Environment \n   \n To host your containerized applications using Azure Container Apps, you must first deploy an Azure Container Apps environment. The environment can host one or more applications and establishes the network boundary, meaning all applications within the shared environment are deployed to the same Azure virtual network. \n   \n As of today, you have the option to bring your own virtual network when creating a new Azure Container Apps environment. If you choose to do so, you will need to provide the network along with a designated subnet: the control plane subnet. The control plane subnet will be used to provide IP addresses from your internal network to the Azure Container Apps control plane infrastructure components as well as your application containers. \n   \n It is important to note that currently, the size of the subnet provided should be at least /23. This subnets should not overlap with the following reserved ranges: \n \n 169.254.0.0/16 \n 172.30.0.0/16 \n 172.31.0.0/16 \n 192.0.2.0/24 \n \n   \n In addition to defining where the service will be deployed, you also have the option to configure inbound access: Internal or External. \n   \n External \n If you choose to deploy an external Azure Container Apps environment, the environment will be accessible via a public endpoint. This endpoint is an Azure Public IP address.  \n   \n \n   \n Internal \n If you would like to lock down your environment from the public internet, you can deploy an internal environment instead. The internal deployment will create an environment that only exposes applications via an IP address from within your virtual network. The list of traffic dependencies required can be found here: Securing a custom VNET in Azure Container Apps | Microsoft Docs.While UDR support is not available today, it is on our roadmap. \n   \n \n   \n Keep in mind, an internal environment will have public IPs, however they will be used solely for outbound connectivity. \n   \n Managed resources \n   \n When you deploy an internal or an external environment into your own network, you will see a new Resource Group with the “MC_” prefix created in the Azure subscription where your environment is hosted. This resource group contains infrastructure components managed by the Azure Container Apps platform. This resource group should not be modified. You will see Public IP addresses which are used specifically for outbound connectivity from your environment as well as an internal or external load balancer depending on your environment configuration. Because the load balancer is created in your subscription, there are additional costs associated with deploying the service to a custom virtual network. \n   \n \n   \n DNS Resolution for Internal Container Apps Environments \n   \n As mentioned in the previous section, an internal-only Azure Container Apps environment will receive an IP address directly from the network provided. By default, there is no domain registration for the internal load balancer (ILB) that is created. This means customers will be responsible for configuring DNS resolution for the environment endpoint. In Azure, this can be accomplished by creating and configuring an Azure Private DNS Zone. \n   \n After deploying the Container Apps environment into a virtual network, you can retrieve the static, internal IP and the default domain. To start hosting the domain in Azure DNS and creating DNS records, the first step is to create the Private DNS Zone. To publish the private DNS zone to your virtual network, you will need to provide a list of virtual networks that are allowed to resolve records within the zone. This list should include the network where your environment is deployed. Once you have created the network link, you can add a wildcard DNS record which will resolve traffic bound for the default domain to the IP address of the environment’s ILB. After completing these steps, your environment will be resolvable by other services in the list of linked networks using the default domain. \n   \n   \n \n   \n Deploying Container Apps to the Container Apps Environment \n   \n At this stage, you can begin deploying your application workloads to the deployed environment! The accessibility level you selected for the environment will impact the available ingress options for your container app deployments. Azure Container Apps provides HTTPS ingress with TLS termination as a built-in feature, so you do not need to deploy an Azure Load Balancer, Public IP address, or any other Azure resources to enable HTTPS ingress. \n   \n If you are deploying to an external environment, you have two options for configuring ingress traffic to your container app: Limited to Container Apps Environment or Accepting traffic from anywhere. You will allow traffic from anywhere if you want the application to be accessible from the public internet. Otherwise, you can choose to allow only traffic from other container apps deployed within the shared Container Apps environment. \n   \n \n   \n   \n If you are deploying to an internal environment, you also have two options for configuring ingress traffic to your container app: Limited to Container Apps Environment or Limited to VNet (Virtual Network). You will allow traffic from the VNet if you want your container app to be accessible from other Azure resources or applications within the virtual network or connected to the virtual network through Peering or some type of VPN connectivity. Otherwise, you can choose to allow only traffic from other container apps deployed within the shared Container Apps environment. \n   \n \n   \n Next Steps \n   \n If you’re looking to learn more about Azure Container Apps and when to use it, check out the latest episode of Microsoft Mechanics. Jeff Hollan shares how the container apps platform plays a critical role in enabling modern applications in the cloud. \n   \n \n   \n If you are interested in learning more about the VNet integration feature specifically, visit the Azure Container Apps custom virtual network Microsoft Docs. We encourage you to share your feedback via our GitHub microsoft/azure-container-apps repo, connect with us on discord and join our mailing list so we can continue enhancing your experience with Azure Container Apps! \n   ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"8326","kudosSumWeight":3,"repliesCount":9,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5Mmk4NzI0NUNBQzYyQUQ0QkYx?revision=9\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5MWlBMjdEOUI3MzIzRjMyMkMx?revision=9\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDEwMGk5Q0U3REQ2N0I4OUNFMUY1?revision=9\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5OGkxQTlGNTUyRDY0MUI4QjZF?revision=9\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDA5NGlENkY5RUMwMTdFODMyRDgy?revision=9\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zMDk2OTMyLTM0NDEwMmk2ODEyRkJDRUQ3ODZCRkFB?revision=9\"}"}}],"totalCount":6,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[{"__typename":"VideoEdge","cursor":"MHxodHRwczovL3lvdXR1LmJlL2IzZG9wU1RuU1JnfDB8MjU7MjV8fA","node":{"__typename":"AssociatedVideo","videoTag":{"__typename":"VideoTag","vid":"https://youtu.be/b3dopSTnSRg","thumbnail":"https://i.ytimg.com/vi/b3dopSTnSRg/hqdefault.jpg","uploading":false,"height":225,"width":400,"title":null},"videoAssociationType":"INLINE_BODY"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:4130496":{"__typename":"Conversation","id":"conversation:4130496","topic":{"__typename":"BlogTopicMessage","uid":4130496},"lastPostingActivityTime":"2024-10-08T00:33:36.928-07:00","solved":false},"User:user:1564375":{"__typename":"User","uid":1564375,"login":"Alibengtsson","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS0xNTY0Mzc1LTU3MjI0NWlFNjYzNTYyRDBBOEUzOTkx"},"id":"user:1564375"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MTMwNDk2LTU3NzIxOGk0OTMwRTg3MjJEMjNERjdE?revision=11\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MTMwNDk2LTU3NzIxOGk0OTMwRTg3MjJEMjNERjdE?revision=11","title":"Alibengtsson_0-1714743413367.jpeg","associationType":"TEASER","width":924,"height":780,"altText":null},"BlogTopicMessage:message:4130496":{"__typename":"BlogTopicMessage","subject":"Azure Kubernetes Service Baseline - The Hard Way","conversation":{"__ref":"Conversation:conversation:4130496"},"id":"message:4130496","revisionNum":11,"uid":4130496,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:1564375"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Are you ready to tackle Kubernetes on Azure like a pro? Embark on the “AKS Baseline - The Hard Way” and prepare for a journey that’s likely to be a mix of command line, detective work and revelations. This is a serious endeavour that will equip you with deep insights and substantial knowledge. \n   \n As you navigate through the intricacies of Azure, you’ll not only face challenges but also accumulate a wealth of learning that will sharpen your skills and broaden your understanding of cloud infrastructure. Get set for an enriching experience that’s all about mastering the ins and outs of Azure Kubernetes Service! \n   \n \n   \n   \n   ","introduction":"","metrics":{"__typename":"MessageMetrics","views":42700},"postTime":"2024-05-03T05:57:00.557-07:00","lastPublishTime":"2024-10-08T00:33:36.928-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":"   \n Azure Kubernetes Service Baseline - The Hard Way \n   \n Welcome to \"Azure Kubernetes Service - The Hard Way\". From this blog, you will learn how to deploy a scalable and resilient Kubernetes cluster on Azure using Azure Kubernetes Service (AKS) and a number of adjacent Azure services. You will also learn how to apply best practices from the AKS baseline reference architecture, which provides a recommended starting point for a general purpose AKS cluster infrastructure. \n   \n The target audience of these instructions is intermediate to advanced Kubernetes users who want to improve their skills and knowledge about AKS and Azure. You will need to have some familiarity with Kubernetes concepts and tools such as pods, services, deployments, and kubectl. You will also need to have an Azure subscription with contributor permission and access to a bash shell. We recommend using Azure Cloud Shell for this, as it has all the necessary tools already installed. \n   \n To access the cloud shell, you can type shell.azure.com in your web browser. Bear in mind that Cloud Shell times out after around 20 minutes of inactivity. Make sure to copy all the environment variables you will be creating, to a file so that you don't loose them. \n Upon finishing, you will have a deeper understanding of how to use AKS to deploy and manage a scalable and resilient Kubernetes cluster on Azure. You will also have a working AKS cluster that follows the AKS baseline reference architecture. Expect the entire exercise to take up to eight hours. \n   \n \n Overview \n   \n The AKS baseline is a reference architecture that provides a set of best practices and recommendations for deploying a scalable and resilient Azure Kubernetes Service (AKS) cluster. One of the key components of the AKS baseline is the network design, which is divided into several subnets and virtual networks (VNets) to isolate and protect the cluster resources from external and internal threats. In this article, we will describe the purpose and configuration of each subnet and VNet in the AKS baseline, and how they work together to provide a robust network infrastructure for your AKS cluster. \n   \n IP Plan \n   \n IP planning is an important aspect of deploying an AKS cluster and Azure services in general, as it affects the scalability, performance, security, and availability of the cluster and its workloads. IP planning involves choosing the right network topology, IP address ranges, subnet sizes, and network policies for the cluster and its nodes, pods, and services. For more information on IP planning for an AKS cluster, see Plan IP addressing for your cluster and Best practices for network resources in AKS. \n This is the proposed IP design that we will adhere to throughout the documentation. \n   \n \n \n Note: IP planning is a crucial step that requires careful consideration of the number and size of subnets for your current solution, as well as the potential for future expansion. You should avoid using excessively large IP ranges, and instead be economical with IP and allocate only what you need for the present and the future. \n \n   \n Each subnet in AKS baseline has a specific purpose and configuration, further information can be found below. \n   \n Hub VNET \n   \n \n \n Azure Firewall Subnet: This subnet is where the Azure Firewall is deployed. The firewall acts as an egress controller for the AKS cluster, filtering and logging the outbound traffic from the cluster to external resources or services. It also provides network address translation (NAT) functionality, which allows the cluster to access resources that are not reachable by private IP addresses. The subnet size can be small for this particular case, as it only needs to accommodate one firewall instance. \n \n \n   \n \n \n Azure Bastion Subnet: This subnet is where the Azure Bastion service is deployed. Azure Bastion is a fully managed service that provides secure and seamless Remote Desktop Protocol (RDP) and Secure Shell (SSH) access to your virtual machines directly through the Azure portal⁴. This subnet is used for management and operations only, and it does not expose any resources to the internet. The subnet name must be AzureBastionSubnet, and the subnet size must be /26 or larger. \n \n \n   \n \n \n Jump Box Subnet: This subnet is where the jump server resides, where operation teams can login and access services in the spoke, to perform operations and maintenance. \n \n \n   \n Spoke VNET \n   \n \n \n Endpoints Subnet: This subnet is where the private endpoints for Azure services are deployed. Private endpoints are a network interface that connects you privately and securely to a service powered by Azure Private Link. Private endpoints allow you to access Azure services, such as Azure Container Registry, Azure Key Vault, or Azure Storage, without exposing them to the internet or requiring a public IP address. The subnet name can be any valid name, and the subnet size depends on the number of private endpoints you need to create. \n \n \n   \n \n \n AKS Subnet: This subnet is where the AKS cluster nodes are deployed. It uses Azure CNI networking, which assigns IP addresses from the subnet to each node and pod. The subnet size depends on the number of nodes and pods per node, and it should be large enough to accommodate the expected growth. The subnet also has a Network Security Group (NSG) that controls the inbound and outbound traffic to and from the nodes. \n \n \n   \n \n \n Azure Application Gateway Subnet: This subnet is where the Azure Application Gateway is deployed. The application gateway acts as an ingress controller for the AKS cluster, routing external traffic to the appropriate services or pods inside the cluster. It also provides web application firewall (WAF) functionality, which helps protect the applications from common web attacks. The subnet size can be small, as it only needs to accommodate one or more application gateway instances. The subnet also has a NSG that allows inbound traffic on ports 80 and 443, and outbound traffic to the AKS cluster. \n \n \n   \n \n \n Azure Loadbalancer Subnet: The load balancer subnet is a part of the network topology that supports the AKS cluster. It is where the internal load balancer (ILB) resides and assigns IP addresses to the services that are exposed within the cluster. \n \n \n   \n Prepare Environment Variables for HUB VNET and SPOKE VNET \n   \n Let’s use the IP plan to set up some environment variables for the Hub VNet and adjust its configuration accordingly to the IP Plan above. Make sure to also save your environment variables to a text file, so that you can restore them later. \n Configure the hub according to the IP Plan (see image above). \n   \n HUB_VNET_NAME=Hub_VNET\nFW_SUBNET_NAME=AzureFirewallSubnet\nBASTION_SUBNET_NAME=AzureBastionSubnet\nHUB_VNET_PREFIX=10.0.0.0/22 # IP address range of the Virtual network (VNet).\nBASTION_SUBNET_PREFIX=10.0.0.128/26 # IP address range of the Bastion subnet \nFW_SUBNET_PREFIX=10.0.0.0/26 # IP address range of the Firewall subnet\nJUMPBOX_SUBNET_PREFIX=10.0.0.64/26 # IP address range of the Jumpbox subnet\n \n Configure the spoke according to the IP Plan (see image above). \n   \n SPOKE_VNET_NAME=Spoke_VNET\nJUMPBOX_SUBNET_NAME=JumpboxSubnet\nENDPOINTS_SUBNET_NAME=endpoints-subnet\nAPPGW_SUBNET_NAME=app-gw-subnet\nAKS_SUBNET_NAME=aks-subnet\nLOADBALANCER_SUBNET_NAME=loadbalancer-subnet\nSPOKE_VNET_PREFIX=10.1.0.0/22 # IP address range of the Virtual network (VNet).\nAKS_SUBNET_PREFIX=10.1.0.0/24 # IP address range of the AKS subnet\nLOADBALANCER_SUBNET_PREFIX=10.1.1.0/28 # IP address range of the Loadbalancer subnet\nAPPGW_SUBNET_PREFIX=10.1.2.0/24 # IP address range of the Application Gateway subnet\nENDPOINTS_SUBNET_PREFIX=10.1.1.16/28 # IP address range of the Endpoints subnet\n \n Infrastructure Deployment \n   \n The objective of this part is to guide you through the process of deploying the AKS baseline infrastructure. The infrastructure consists of the essential components and configurations that are required for running a secure and scalable AKS cluster. \n   \n Prepare Environment Variables for infrastructure \n   \n This configuration sets up environment variables for the names and locations of various network and security resources, such as resource groups, virtual networks, subnets, network security groups, firewall, application gateway, route table, identity, virtual machines, AKS cluster, and ACR registry. \n   \n \n Note: Since the Azure container registry has a globally unique FQDN name, you need to assign a distinct value to the ACR_NAME environment variable, else the ACR deployment will fail. Also, the ACR name can only container lowercase letters and numbers. \n \n   \n HUB_RG=rg-hub\nSPOKE_RG=rg-spoke\nLOCATION=eastus \nBASTION_NSG_NAME=Bastion_NSG\nJUMPBOX_NSG_NAME=Jumpbox_NSG\nAKS_NSG_NAME=Aks_NSG\nENDPOINTS_NSG_NAME=Endpoints_NSG\nLOADBALANCER_NSG_NAME=Loadbalancer_NSG\nAPPGW_NSG=Appgw_NSG\nFW_NAME=azure-firewall\nAPPGW_NAME=AppGateway\nROUTE_TABLE_NAME=spoke-rt\nAKS_IDENTITY_NAME=aks-msi\nJUMPBOX_VM_NAME=Jumpbox-VM\nAKS_CLUSTER_NAME=private-aks\nACR_NAME=<Globally unique name of the azure container registry>\nSTUDENT_NAME=<e.g. your first name> # don't use spaces\n \n Create the Resource Groups for the Hub and Spoke. \n   \n az group create --name $HUB_RG --location $LOCATION\naz group create --name $SPOKE_RG --location $LOCATION\n \n Create Network Security Groups (NSG) and Virtual Network (VNET) for the Hub. \n   \n In this step, we will begin by establishing Network Security Groups (NSGs) that will subsequently be associated with their respective subnet. It is crucial to note that there are specific prerequisites concerning security rules for certain subnets that must be met before a service can be deployed. Azure Bastion is one of them. \n For Azure Bastion, we are establishing security rules to permit both the control and data plane access to the AzureBastion. For a more detailed understanding of these rules, please refer to the following resource: More Information. \n   \n \n Create the NSG for AzureBastionSubnet. \n \n az network nsg create \\\n --resource-group $HUB_RG \\\n --name $BASTION_NSG_NAME \\\n --location $LOCATION\n \n \n Associate the required inbound security rules to the NSG. \n \n az network nsg rule create --name AllowHttpsInbound \\\n --nsg-name $BASTION_NSG_NAME --priority 120 --resource-group $HUB_RG\\\n --access Allow --protocol TCP --direction Inbound \\\n --source-address-prefixes \"Internet\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"*\" \\\n --destination-port-ranges \"443\"\n\t\n \taz network nsg rule create --name AllowGatewayManagerInbound \\\n --nsg-name $BASTION_NSG_NAME --priority 130 --resource-group $HUB_RG\\\n --access Allow --protocol TCP --direction Inbound \\\n --source-address-prefixes \"GatewayManager\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"*\" \\\n --destination-port-ranges \"443\"\n\t\n\taz network nsg rule create --name AllowAzureLoadBalancerInbound \\\n --nsg-name $BASTION_NSG_NAME --priority 140 --resource-group $HUB_RG\\\n --access Allow --protocol TCP --direction Inbound \\\n --source-address-prefixes \"AzureLoadBalancer\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"*\" \\\n --destination-port-ranges \"443\"\n\t\n\t\n\taz network nsg rule create --name AllowBastionHostCommunication \\\n --nsg-name $BASTION_NSG_NAME --priority 150 --resource-group $HUB_RG\\\n --access Allow --protocol TCP --direction Inbound \\\n --source-address-prefixes \"VirtualNetwork\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"VirtualNetwork\" \\\n --destination-port-ranges 8080 5701\n \n \n Associate the required outbound security rules to the NSG. \n \n az network nsg rule create --name AllowSshRdpOutbound \\\n --nsg-name $BASTION_NSG_NAME --priority 100 --resource-group $HUB_RG\\\n --access Allow --protocol \"*\" --direction outbound \\\n --source-address-prefixes \"*\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"VirtualNetwork\" \\\n --destination-port-ranges 22 3389\n\t\n az network nsg rule create --name AllowAzureCloudOutbound \\\n --nsg-name $BASTION_NSG_NAME --priority 110 --resource-group $HUB_RG\\\n --access Allow --protocol Tcp --direction outbound \\\n --source-address-prefixes \"*\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"AzureCloud\" \\\n --destination-port-ranges 443\n\t\n\taz network nsg rule create --name AllowBastionCommunication \\\n --nsg-name $BASTION_NSG_NAME --priority 120 --resource-group $HUB_RG\\\n --access Allow --protocol \"*\" --direction outbound \\\n --source-address-prefixes \"VirtualNetwork\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"VirtualNetwork\" \\\n --destination-port-ranges 8080 5701\n\t\n\taz network nsg rule create --name AllowHttpOutbound \\\n --nsg-name $BASTION_NSG_NAME --priority 130 --resource-group $HUB_RG\\\n --access Allow --protocol \"*\" --direction outbound \\\n --source-address-prefixes \"*\" \\\n --source-port-ranges \"*\" \\\n --destination-address-prefixes \"Internet\" \\\n --destination-port-ranges 80\n \n \n Create an NSG for the JumpBox subnet. \n \n az network nsg create \\\n --resource-group $HUB_RG \\\n --name $JUMPBOX_NSG_NAME \\\n --location $LOCATION\n \n \n Create the HUB VNET with one subnet for Azure Bastion Subnet and associate it to the bastion NSG. \n \n az network vnet create \\\n --resource-group $HUB_RG \\\n --name $HUB_VNET_NAME \\\n --address-prefixes $HUB_VNET_PREFIX \\\n --subnet-name $BASTION_SUBNET_NAME \\\n --subnet-prefixes $BASTION_SUBNET_PREFIX \\\n --network-security-group $BASTION_NSG_NAME\n \n \n Create a subnet for the Azure Firewall. \n \n az network vnet subnet create \\\n --resource-group $HUB_RG \\\n --vnet-name $HUB_VNET_NAME \\\n --name $FW_SUBNET_NAME \\\n --address-prefixes $FW_SUBNET_PREFIX\n \n \n Create a subnet for the Virtual Machine that will be used as \"jumpbox\". \n \n az network vnet subnet create \\\n --resource-group $HUB_RG \\\n --vnet-name $HUB_VNET_NAME \\\n --name $JUMPBOX_SUBNET_NAME \\\n --address-prefixes $JUMPBOX_SUBNET_PREFIX \\\n --network-security-group $JUMPBOX_NSG_NAME\n \n You have successfully configured the network for your hub virtual network.You have established three subnets and two NSGs, as depicted on the image: \n   \n   \n \n \n \n To Validate your deployment, navigate to the Azure portal at https://portal.azure.com and enter your login credentials. \n \n \n Once logged in, locate and select your resource group called rg-hub where the hub vnet is deployed. \n \n \n Select your vnet called HUB_VNET. \n \n \n In the left-hand side menu, under the Settings section, select Subnets. \n \n \n Make sure that your subnets have the appropriate IP range and that Network Security Groups (NSGs) are correctly associated with their respective subnets as depicted below. \n \n \n   \n \n   \n Create Network Security Groups and Virtual Network for the Spoke. \n   \n We will now start to setup the spoke vnet, subnets and their respective NSGs. \n \n Create the NSG for AKS subnet. \n \n az network nsg create \\\n --resource-group $SPOKE_RG \\\n --name $AKS_NSG_NAME \\\n --location $LOCATION\n \n \n Create the NSG for endpoints subnet, were the endpoints will reside. \n \n az network nsg create \\\n --resource-group $SPOKE_RG \\\n --name $ENDPOINTS_NSG_NAME \\\n --location $LOCATION\n \n \n Create the NSG for load balancer subnet, were the internal load balancer will reside. \n \n az network nsg create \\\n --resource-group $SPOKE_RG \\\n --name $LOADBALANCER_NSG_NAME \\\n --location $LOCATION\n \n \n To use an NSG with your application gateway, you need to open these port ranges: \n \n Inbound rules: The Internet service tag needs access to port 65200-65535 for the backend health API. Your application traffic needs access to TCP port 80 and/or 443. for futher information refer to Required security rules for Application Gateway for more information. \n az network nsg create \\\n --resource-group $SPOKE_RG \\\n --name $APPGW_NSG \\\n --location $LOCATION\n \n \n Create the NSG rule to allow application traffic, on port 443 and 80. \n \n # Allow Internet Client request on Port 443 and 80\naz network nsg rule create \\\n --resource-group $SPOKE_RG \\\n --nsg-name $APPGW_NSG \\\n --name Allow-Internet-Inbound-HTTP-HTTPS \\\n --priority 100 \\\n --source-address-prefixes Internet \\\n --destination-port-ranges 80 443 \\\n --access Allow \\\n --protocol Tcp \\\n --description \"Allow inbound traffic to port 80 and 443 to Application Gateway from client requests originating from the Internet\"\n \n \n Create the NSG rule to allow application traffic, on port range 65200-65535. \n \n # Infrastructure ports\naz network nsg rule create \\\n --resource-group $SPOKE_RG \\\n --nsg-name $APPGW_NSG \\\n --name Allow-GatewayManager-Inbound \\\n --priority 110 \\\n --source-address-prefixes \"GatewayManager\" \\\n --destination-port-ranges 65200-65535 \\\n --access Allow \\\n --protocol Tcp \\\n --description \"Allow inbound traffic to ports 65200-65535 from GatewayManager service tag\"\n \n \n Create the spoke VNET with one subnet for AKS Subnet and associate it to the AKS NSG. \n \n az network vnet create \\\n --resource-group $SPOKE_RG \\\n --name $SPOKE_VNET_NAME \\\n --address-prefixes $SPOKE_VNET_PREFIX \\\n --subnet-name $AKS_SUBNET_NAME \\\n --subnet-prefixes $AKS_SUBNET_PREFIX \\\n\t--network-security-group $AKS_NSG_NAME\n \n \n Create the subnet for Endpoints and associate it to the endpoints NSG. \n \n az network vnet subnet create \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --name $ENDPOINTS_SUBNET_NAME \\\n --address-prefixes $ENDPOINTS_SUBNET_PREFIX \\\n\t--network-security-group $ENDPOINTS_NSG_NAME\n \n \n Create subnet for the load balancer that will be used for ingress traffic and associate it to the loadbalancer NSG. \n \n az network vnet subnet create \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --name $LOADBALANCER_SUBNET_NAME \\\n --address-prefixes $LOADBALANCER_SUBNET_PREFIX \\\n\t--network-security-group $LOADBALANCER_NSG_NAME\n \n \n Create subnet for the Application Gateway and associate it to the Application Gateway NSG. \n \n az network vnet subnet create \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --name $APPGW_SUBNET_NAME \\\n --address-prefixes $APPGW_SUBNET_PREFIX \\\n\t--network-security-group $APPGW_NSG\n \n   \n You have successfully configured the network for your spoke virtual network. You should now have established the following setup in your Azure subscription. \n   \n   \n \n   \n \n \n Navigate to the Azure portal at https://portal.azure.com again. \n \n \n Locate and select your resource group called rg-spoke where the spoke vnet is deployed. \n \n \n Select the vnet called Spoke_VNET. \n \n \n In the left-hand side menu, under the Settings section, select Subnets. \n \n \n Make sure that your subnets have the appropriate IP range and that Network Security Groups (NSGs) are correctly associated with their respective subnets. \n \n \n   \n \n   \n Create VNET Peering Between Hub and Spoke \n   \n The next step is to create a virtual network peering between the hub and spoke VNets. This will enable the communication between the VNETs and allow the AKS cluster to route traffic to the Firewall. \n   \n \n Before we can do a VNET peering we need to obtain the full resource id of the Spoke_VNET and Hub_VNET as they resides in different resource groups. \n \n SPOKE_VNET_ID=$(az network vnet show --resource-group $SPOKE_RG --name $SPOKE_VNET_NAME --query id --output tsv)\n \n HUB_VNET_ID=$(az network vnet show --resource-group $HUB_RG --name $HUB_VNET_NAME --query id --output tsv)\n \n \n Now, create a peering connection from the hub to the spoke virtual network. \n \n az network vnet peering create \\\n --resource-group $HUB_RG \\\n --name hub-to-spoke \\\n --vnet-name $HUB_VNET_NAME \\\n --remote-vnet $SPOKE_VNET_ID \\\n --allow-vnet-access\n \n \n Then create a peering connection from the spoke to hub virtual network. \n \n az network vnet peering create \\\n --resource-group $SPOKE_RG \\\n --name spoke-to-hub \\\n --vnet-name $SPOKE_VNET_NAME \\\n --remote-vnet $HUB_VNET_ID \\\n --allow-vnet-access\n \n Peering should be established and the high level design should now look like this: \n   \n   \n \n   \n \n \n Navigate to the Azure portal at https://portal.azure.com \n \n \n Locate and select the resource group called rg-spoke where the spoke vnet is deployed. \n \n \n Select the vnet called Spoke_VNET. \n \n \n In the left-hand side menu, under the Settings section, select peerings. \n \n \n Ensure that the peering status is set to Connected. \n \n \n Repeat step 4 - 7 but for Hub_VNET. \n \n \n   \n \n   \n Create Azure Bastion and Jumpbox VM \n   \n \n The Bastion Host needs a Public IP. Create the Public IP address. \n \n az network public-ip create \\\n --resource-group $HUB_RG \\\n --name Bastion-PIP \\\n --sku Standard \\\n --allocation-method Static\n \n \n Create JumpBox Virtual Machine. \n \n \n Note: Ensure you specify a password for the admin user called azureuser. The password length must be between 12 and 72. Password must have 3 of the following: 1 lower case character, 1 upper case character, 1 number and 1 special character. \n \n   \n az vm create \\\n --resource-group $HUB_RG \\\n --name $JUMPBOX_VM_NAME \\\n --image Ubuntu2204 \\\n --admin-username azureuser \\\n --admin-password <SPECIFY A PASSWORD HERE> \\\n --vnet-name $HUB_VNET_NAME \\\n --subnet $JUMPBOX_SUBNET_NAME \\\n --size Standard_B2s \\\n --storage-sku Standard_LRS \\\n --os-disk-name $JUMPBOX_VM_NAME-VM-osdisk \\\n --os-disk-size-gb 128 \\\n --public-ip-address \"\" \\\n --nsg \"\" \n \n \n Create the bastion host in hub vnet and associate it to the public IP. \n \n \n Note: Azure Bastion service requires a dedicated subnet named AzureBastionSubnet to provide secure and seamless RDP/SSH connectivity to your virtual machines. When you deploy Azure Bastion service, it will automatically create this subnet for you, if it does not exist in the target virtual network. However, if the subnet already exists, it must meet the minimum size of /26 or larger, otherwise the deployment will fail. \n \n   \n az network bastion create \\\n --resource-group $HUB_RG \\\n --name bastionhost \\\n --public-ip-address Bastion-PIP \\\n --vnet-name $HUB_VNET_NAME \\\n --location $LOCATION\n \n \n \n Upon successful installation of the Jumpbox Virtual Machine (VM). Navigate to the Azure portal at https://portal.azure.com \n \n \n Locate and select your rg-hub where the Jumpbox has been deployed. \n \n \n Within your resource group, find and click on the Jumpbox VM. \n \n \n In the left-hand side menu, under the Connect section, select ‘Bastion’. \n \n \n Enter the credentials for the Jumpbox VM and verify that you can log in successfully. \n \n \n For additional information on accessing VMs through Bastion, please refer to this Microsoft Azure Bastion tutorial \n After completing these steps, The high-level targeted architecture now matches the following diagram: \n   \n   \n \n   \n Create an Azure Firewall and Setup a User Defined Route (UDR) \n   \n To secure your outbound traffic, you can use an Azure Firewall. The following steps will help you restrict the outbound access and to certain FQDNs that are needed by the cluster. further information can be found here: Control egress traffic using Azure Firewall in Azure Kubernetes Service (AKS) \n   \n \n Create Azure Firewall, and deploy it to it to firewall subnet in hub vnet. \n \n az network firewall create \\\n --resource-group $HUB_RG \\\n --name $FW_NAME \\\n --location $LOCATION \\\n --vnet-name $HUB_VNET_NAME \\\n --enable-dns-proxy true\n\n \n \n The firewall needs a Public IP address. Create the Public IP. \n \n az network public-ip create \\\n --name fw-pip \\\n --resource-group $HUB_RG \\\n --location $LOCATION \\\n --allocation-method static \\\n --sku standard\n\n \n \n Associate the public IP address with the Firewall. \n \n az network firewall ip-config create \\\n --firewall-name $FW_NAME \\\n --name FW-config \\\n --public-ip-address fw-pip \\\n --resource-group $HUB_RG \\\n --vnet-name $HUB_VNET_NAME\n\n \n \n Update the existing Azure Firewall configuration. \n \n az network firewall update \\\n --name $FW_NAME \\\n --resource-group $HUB_RG \n \n \n Create Network rules in Azure Firewall. \n \n   \n The following network rules allows outbound traffic from any source address to certain destinations and ports. If the required destination is not specified the AKS cluster will fail to deploy. \n Please note that these transactions are slow. Expect each rule to require around 5 minutes to complete. \n az network firewall network-rule create -g $HUB_RG -f $FW_NAME --collection-name 'aksfwnr' -n 'apiudp' --protocols 'UDP' --source-addresses '*' --destination-addresses \"AzureCloud.$LOCATION\" --destination-ports 1194 --action allow --priority 100\n\n\naz network firewall network-rule create -g $HUB_RG -f $FW_NAME --collection-name 'aksfwnr' -n 'apitcp' --protocols 'TCP' --source-addresses '*' --destination-addresses \"AzureCloud.$LOCATION\" --destination-ports 9000\n\n\naz network firewall network-rule create -g $HUB_RG -f $FW_NAME --collection-name 'aksfwnr' -n 'time' --protocols 'UDP' --source-addresses '*' --destination-fqdns 'ntp.ubuntu.com' --destination-ports 123\n \n \n Create Azure Firewall application rule. \n \n This rule specifies the FQDN's which are required by AKS, AzureKubernetesService tag which include all the FQDNs listed in Outbound network and FQDN rules for AKS clusters. \n   \n For more information about required egress destinations, see Outbound network and FQDN rules for Azure Kubernetes Service (AKS) clusters \n az network firewall application-rule create -g $HUB_RG -f $FW_NAME --collection-name 'aksfwar' -n 'fqdn' --source-addresses '*' --protocols 'http=80' 'https=443' --fqdn-tags \"AzureKubernetesService\" --action allow --priority 100\n \n \n Create a route table in the spoke. \n \n az network route-table create \\\n --resource-group $SPOKE_RG \\\n --name $ROUTE_TABLE_NAME\n\n \n \n Create a route to the internet via the Azure Firewall. \n \n In order to create the route we need to obtain the private IP address of the Firewall.To get the private IP address of the Firewall, you need to run the following command: \n az network firewall show --resource-group $HUB_RG --name $FW_NAME |grep privateIPAddress\n \n Then store the output (the ip address) in an environment variable: \n FW_PRIVATE_IP=<IP Address from previous command>\n \n Create the route table to route egress traffic to the firewall in the hub VNET: \n az network route-table route create \\\n --resource-group $SPOKE_RG \\\n --name default-route \\\n --route-table-name $ROUTE_TABLE_NAME \\\n --address-prefix 0.0.0.0/0 \\\n --next-hop-type VirtualAppliance \\\n --next-hop-ip-address $FW_PRIVATE_IP\n\n \n \n Note: The route will direct all traffic (0.0.0.0/0) to the next hop type of VirtualAppliance, which is the firewall instance. The next hop IP address is the private IP address of the firewall, which is stored in the environment variable $FW_PRIVATE_IP. This way, the traffic from the AKS subnet will be routed to the firewall instance on its private endpoint. This will allow you to perform inspection on outbound traffic. \n \n   \n \n Associate the route table with the AKS subnet. \n \n az network vnet subnet update \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --name $AKS_SUBNET_NAME \\\n --route-table $ROUTE_TABLE_NAME\n \n You have successfully configured the firewall in the hub VNet, set up network and application rules, and created a route table associated with the AKS subnet to direct all internet-bound traffic through the Azure Firewall. \n   \n   \n \n   \n \n   \n \n \n To validate your deployment, navigate to the Azure portal at https://portal.azure.com \n \n \n Locate and select your resource group called rg-hub where the hub vnet is deployed. \n \n \n Select your firewall called azure-firewall. \n \n \n In the left-hand side menu, under the Settings section, select Rules. \n \n \n Click on Network rule collection \n \n \n Verify that you have a network rule collection called aksfwnr which should contain 3 rules. Inspect the rules. \n \n \n   \n \n   \n \n \n Click on Application rule collection. \n \n \n Verify that you have an application rule collection called aksfwar which should contain 1 rule. Inspect the rule. \n \n \n   \n \n \n \n Lets validate the routing between AKS subnet and Azure Firewall, in the Azure portal, in the top menu select Resource Groups. \n \n \n Select resource group rg-spoke. \n \n \n Select routing table called spoke-rt. \n \n \n Ensure that the default route has a prefix of 0.0.0.0/0 and the next hop is set to the virtual appliance with the IP address of the Azure Firewall. Also, make sure that the routing table is associated with the AKS subnet called aks-subnet. \n \n \n   \n \n   \n Deploy Azure Kubernetes Service \n   \n This part covers deploying AKS with outbound traffic configured to use a user-defined routing table, ensuring traffic passes through the Azure Firewall. A private DNS zone is also created when deploying a private AKS cluster. A user-assigned identity with necessary permissions is assigned to the cluster and load balancer subnet. This identity is a type of managed identity in Azure. \n   \n \n Create a user-assigned managed identity. \n \n az identity create \\\n --resource-group $SPOKE_RG \\\n --name $AKS_IDENTITY_NAME-${STUDENT_NAME}\n \n \n Get the id of the user managed identity. \n \n IDENTITY_ID=$(az identity show \\\n --resource-group $SPOKE_RG \\\n --name $AKS_IDENTITY_NAME-${STUDENT_NAME} \\\n --query id \\\n --output tsv)\n \n \n Get the principal id of the user managed identity. \n \n PRINCIPAL_ID=$(az identity show \\\n --resource-group $SPOKE_RG \\\n --name $AKS_IDENTITY_NAME-${STUDENT_NAME} \\\n --query principalId \\\n --output tsv)\n \n \n Get the scope of the routing table. \n \n RT_SCOPE=$(az network route-table show \\\n --resource-group $SPOKE_RG \\\n --name $ROUTE_TABLE_NAME \\\n --query id \\\n --output tsv)\n \n \n Assign permissions for the AKS user defined managed identity to the routing table. \n \n az role assignment create \\\n --assignee $PRINCIPAL_ID\\\n --scope $RT_SCOPE \\\n --role \"Network Contributor\"\n \n \n Assign permission for the AKS user defined managed identity to the load balancer subnet. \n \n LB_SUBNET_SCOPE=$(az network vnet subnet list \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --query \"[?name=='$LOADBALANCER_SUBNET_NAME'].id\" \\\n --output tsv)\n \n az role assignment create \\\n --assignee $PRINCIPAL_ID \\\n --scope $LB_SUBNET_SCOPE \\\n --role \"Network Contributor\"\n\n \n \n Note: Granting the Network Contributor role to the load balancer subnet in AKS could result in over-privileged access. To minimize security risks, it is recommended to only provide AKS with the necessary permissions to function effectively, adhering to the principle of least privilege access. For more information refer to Creating Azure custom role. \n \n   \n \n Retrieve the scope of AKS subnet, were AKS shall be deployed. \n \n AKS_SUBNET_SCOPE=$(az network vnet subnet list \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --query \"[?name=='$AKS_SUBNET_NAME'].id\" \\\n --output tsv)\n \n \n Deploy a Highly Available Private AKS Cluster. \n \n   \n To deploy a highly available private AKS cluster, you can use the following command: \n This command creates an AKS cluster with two system nodes, using the specified VNet subnet ID and cluster name. It is configured as a private cluster with user-defined routing and OIDC issuer and workload identity enabled. The network plugin and policy are set to Azure, and the public FQDN is disabled. The cluster is deployed across availability zones 1, 2, and 3. \n   \n For more information about OIDC and Workload Identity refer to Use Microsoft Entra Workload ID with Azure Kubernetes Service (AKS) \n   \n az aks create --resource-group $SPOKE_RG --node-count 2 --vnet-subnet-id $AKS_SUBNET_SCOPE --name $AKS_CLUSTER_NAME-${STUDENT_NAME} --enable-private-cluster --outbound-type userDefinedRouting --enable-oidc-issuer --enable-workload-identity --generate-ssh-keys --assign-identity $IDENTITY_ID --network-plugin azure --network-policy azure --disable-public-fqdn --zones 1 2 3\n \n \n Note: A private AKS cluster has its Kubernetes API endpoint isolated from public access, allowing access only within the same virtual network. To communicate with the private AKS cluster from a jumpbox in a different virtual network, a virtual network link must be created between the two networks for DNS resolution. This will be covered in a later section. \n \n   \n \n An additional nodepool will be created to host user workloads. Auto-scaling is enabled to allow for automatic scaling out and scaling in based on demand. The worker nodes will be distributed across three different zones to ensure higher availability. \n \n az aks nodepool add --resource-group $SPOKE_RG --cluster-name $AKS_CLUSTER_NAME-${STUDENT_NAME} --name userpool --node-count 3 --mode user --zones 1 2 3 --enable-cluster-autoscaler --min-count 1 --max-count 5\n \n \n Create a virtual network link to resolve AKS private endpoint from HUB vnet. \n \n   \n Fetch the node group of the AKS cluster, and save it in an environment variable. \n NODE_GROUP=$(az aks show --resource-group $SPOKE_RG --name $AKS_CLUSTER_NAME-${STUDENT_NAME} --query nodeResourceGroup -o tsv)\n \n Fetch the AKS DNS zone name. \n DNS_ZONE_NAME=$(az network private-dns zone list --resource-group $NODE_GROUP --query \"[0].name\" -o tsv)\n\n \n Fetch the ID of the HUB virtual network. \n HUB_VNET_ID=$(az network vnet show -g $HUB_RG -n $HUB_VNET_NAME --query id --output tsv)\n \n Create a virtual network link between the hub virtual network and the AKS private DNS zone, that was created for the AKS cluster. \n az network private-dns link vnet create --name \"hubnetdnsconfig\" --registration-enabled false --resource-group $NODE_GROUP --virtual-network $HUB_VNET_ID --zone-name $DNS_ZONE_NAME \n \n Validate your deployment in the Azure portal. \n \n \n Navigate to the Azure portal at https://portal.azure.com. \n \n \n Click on Resource groups to view all of your resource groups in your subscription. You should have 3 RGs which you have created,MC_rg-spoke_private-aks-xxxx_eastus, rg-hub and rg-spoke \n \n \n   \n \n Note: MC_rg-spoke_private-aks-xxxx_eastus is a resource group automatically created when deploying an AKS cluster. It is used by Azure to manage resources for the cluster, this particular resource group is also known as Node group. \n \n   \n   \n \n   \n \n \n Verify that a virtual network link exists between the Hub and spoke to enable the jumpbox to resolve the AKS domain name and access the cluster. Select the node group called MC_rg-spoke_private-aks-xxxxx_eastus. \n \n \n Select the Private DNS zone. \n \n \n On your left hand side menu, under Settings click on Virtual network links. \n \n \n Validate that there is a link name called hubnetdnsconfig and the link status is set to Completed and the virtual network is set to Hub_VNET. \n \n \n   \n \n   \n \n \n On the top menu click Resource groups and choose rg-spoke from the resource group list. \n \n \n Click on the AKS resource called private-aks-. Verify that the Private cluster is set to Enabled. \n \n \n   \n \n   \n \n Verify AKS control plane connectivity. \n \n In this section we will verify that we are able to connect to the AKS cluster from the jumpbox, firstly we need to connect to the cluster successfully and secondly we need to verify that the kubernetes client is able to communicate with the AKS control plane from the jumpbox. \n   \n \n \n Select resource group rg-hub where the Jumpbox has been deployed. \n \n \n Within your resource group, find and click on the virtual machine called Jumpbox VM. \n \n \n In the left-hand side menu, under Connect section, select Bastion. \n \n \n Enter the credentials for the Jumpbox VM and verify that you can log in successfully. \n \n \n Once successfully logged in to the jumpbox you need to install a few tools. Run the commands one by one, or create a bash script. \n \n \n   \n # Update apt repo\nsudo apt update \n# Install Docker\nsudo apt install docker.io -y\n# Install azure CLI\ncurl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash\n# Install AKS CLI (kubectl)\nsudo az aks install-cli\n# Add user to Docker group\nsudo usermod -aG docker $USER\n \n \n Now, login to Azure in order to obtain AKS credentials. \n \n az login\naz account set --subscription <SUBSCRIPTION ID>\n \n \n Note: To check the current subscription, run the command: az account show To change the subscription, run the command: az account set --subscription , where the ID of the desired subscription. You can find the subscription ID by running the command: az account list --output table \n \n   \n \n Add your Environment variables to the jumpbox bash shell. \n \n SPOKE_RG=rg-spoke\nAKS_CLUSTER_NAME=private-aks\nSTUDENT_NAME=<WRITE YOUR STUDENT NAME HERE>\n \n \n Download the AKS credentials onto the jumpbox. \n \n az aks get-credentials --resource-group $SPOKE_RG --name $AKS_CLUSTER_NAME-${STUDENT_NAME}\n \n \n Ensure you can list resources in AKS. \n \n kubectl get nodes\n \n The following output shows the result of running the command kubectl get nodes on with kubectl CLI. \n azureuser@Jumpbox-VM:~$ kubectl get nodes\nNAME STATUS ROLES AGE VERSION\naks-nodepool1-12240482-vmss000000 Ready agent 89m v1.27.9\naks-nodepool1-12240482-vmss000001 Ready agent 89m v1.27.9\naks-userpool-16991029-vmss000000 Ready agent 78m v1.27.9\n \n \n Log out from the Jumpbox host. \n \n Congratulations! You have completed the steps to deploy a private AKS cluster and configure its network settings. You have assigned a user assigned identity to the cluster that has the required permissions to modify the user-defined routing table and load balancer subnet. You have also created a virtual network link between the hub virtual network and the private DNS zone of the cluster. This enables the jumpbox to resolve the private API server of the cluster and access it for management and maintenance purposes. \n   \n \n   \n \n   \n Deploy Azure Container Registry \n   \n In this section, we will learn how to deploy a private Azure Container Registry that will store our container images. A private container registry is a type of container registry that is not accessible from the public internet. To enable access to the private container registry from the jumpbox, we need to create some networking resources that will allow us to resolve the container registry name and connect to it securely. These resources are: a private endpoint, a private link, and a virtual network link. We will see how to create and configure these resources in the following steps. We will also test the connection to the private container registry by pushing some images to it from the jumpbox. \n   \n   \n \n Create the Azure Container Registry, and disable public access to the registry. \n \n az acr create \\\n --resource-group $SPOKE_RG \\\n --name $ACR_NAME \\\n --sku Premium \\\n --admin-enabled false \\\n --location $LOCATION \\\n --allow-trusted-services false \\\n --public-network-enabled false\n \n \n IMPORTANT: Ensure you have a globally unique name for your ACR, or else the deployment will fail. \n \n \n Configure the private DNS zone for ACR. \n \n az network private-dns zone create \\\n --resource-group $SPOKE_RG \\\n --name \"privatelink.azurecr.io\"\n \n \n Create a virtual network link to the spoke network. \n \n az network private-dns link vnet create \\\n --resource-group $SPOKE_RG \\\n --zone-name \"privatelink.azurecr.io\" \\\n --name ACRDNSSpokeLink \\\n --virtual-network $SPOKE_VNET_NAME \\\n --registration-enabled false\n \n \n Create a virtual network link to the hub network. \n \n \n Note: The $HUB_VNET_ID variable specifies the full path to the virtual network in another resource group, allowing the command to correctly link to it. Make sure the environment variable $HUB_VNET_ID is populated before running the command below. If it is empty, just rerun the command: \n \n HUB_VNET_ID=$(az network vnet show --resource-group $HUB_RG --name $HUB_VNET_NAME --query id --output tsv)\n \n   \n \n az network private-dns link vnet create \\\n --resource-group $SPOKE_RG \\\n --zone-name \"privatelink.azurecr.io\" \\\n --name ACRDNSHubLink \\\n --virtual-network $HUB_VNET_ID \\\n --registration-enabled false\n \n \n Create ACR private endpoint. \n \n   \n To create a private endpoint for an Azure Container Registry (ACR), you need to obtain the resource ID of the container registry. This resource ID is used to specify the target resource when creating the private endpoint. \n REGISTRY_ID=$(az acr show --name $ACR_NAME \\\n --query 'id' --output tsv)\n\n \n az network private-endpoint create \\\n --name ACRPrivateEndpoint \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --subnet $ENDPOINTS_SUBNET_NAME \\\n --private-connection-resource-id $REGISTRY_ID \\\n --group-ids registry \\\n --connection-name PrivateACRConnection\n \n \n Configure DNS record for ACR. \n \n   \n In this section we will configure DNS records for an Azure Container Registry (ACR) using Azure Private Link.This is to ensure that the ACR can be accessed over a private network connection, enhancing security by eliminating exposure to the public internet. \n Before we can configure the DNS record we need to obtain the private IP address of the ACR, both the control and data plane. \n Get endpoint IP configuration: \n   \n NETWORK_INTERFACE_ID=$(az network private-endpoint show \\\n --name ACRPrivateEndpoint \\\n --resource-group $SPOKE_RG \\\n --query 'networkInterfaces[0].id' \\\n --output tsv)\n \n Fetch the private IP address associated with the ACR. These IP addresses are used for data and control of the container registry. \n az network nic show --ids $NETWORK_INTERFACE_ID |grep azurecr.io -B 7\n \n In the output you should see two IP addresses, and their associated FQDNS. It should look similar to this: \n \"name\": \"privateEndpointIpConfig.9c4c0ee4-c187-4094-aede-fc0dabb70236\",\n \"primary\": true,\n \"privateIPAddress\": \"10.1.1.20\",\n \"privateIPAddressVersion\": \"IPv4\",\n \"privateIPAllocationMethod\": \"Dynamic\",\n \"privateLinkConnectionProperties\": {\n \"fqdns\": [\n \"acrforakssecurity.westus2.data.azurecr.io\"\n--\n \"name\": \"privateEndpointIpConfig.7ffb814c-aacc-4199-a07d-35f61df0ea1f\",\n \"primary\": false,\n \"privateIPAddress\": \"10.1.1.21\",\n \"privateIPAddressVersion\": \"IPv4\",\n \"privateIPAllocationMethod\": \"Dynamic\",\n \"privateLinkConnectionProperties\": {\n \"fqdns\": [\n \"acrforakssecurity.azurecr.io\"\n \n Note down the privateIPAddress and fqdns as it will be used in a later step (when creating DNS zones). \n \n Create a new 'A' record set for control in the private DNZ zone. \n \n az network private-dns record-set a create \\\n --name $ACR_NAME \\\n --zone-name privatelink.azurecr.io \\\n --resource-group $SPOKE_RG\n \n \n Create a new 'A' record set for data in the private DNZ zone. \n \n az network private-dns record-set a create \\\n --name $ACR_NAME.$LOCATION.data \\\n --zone-name privatelink.azurecr.io \\\n --resource-group $SPOKE_RG\n \n \n Update the 'A' record to contain the data IP address of the ACR. \n \n az network private-dns record-set a add-record \\\n --record-set-name $ACR_NAME.$LOCATION.data \\\n --zone-name privatelink.azurecr.io \\\n --resource-group $SPOKE_RG \\\n --ipv4-address <IP address assicoated with FQDN \"$ACR_NAME.$LOCATION.data.azurecr.io\">\n \n \n Update the 'A' record to contain the control IP address of the ACR. \n \n az network private-dns record-set a add-record \\\n --record-set-name $ACR_NAME \\\n --zone-name privatelink.azurecr.io \\\n --resource-group $SPOKE_RG \\\n --ipv4-address <IP address associated with FQDN \"$ACR_NAME.azurecr.io\">\n \n Validate your deployment in the Azure portal. \n \n \n Navigate to the Azure portal at https://portal.azure.com and enter your login credentials. \n \n \n log in and select the rg-spoke resource group. Verify that you have a container registry and a private endpoint named ACRPrivateEndpoint deployed in your resource group, as well as a network card named ACRPrivateEndpoint.nic.xxxxx. \n \n \n   \n \n   \n \n Select the private DNS zone named privatelink.azurecr.io. Ensure that you have two ‘A’ records, one for control and one for data, and that the correct IP addresses are configured. \n \n   \n \n \n In the left-hand side menu, under Settings section, select Virtual Network links. Ensure you have the link status set to completed for both hub and spoke. \n \n   \n \n \n Test the connection to ACR from the Jumpbox. \n \n In this section, you will learn how to check if you can access your private Azure Container Registry (ACR) and push Docker images to it. You will need to have the Azure CLI installed and logged in to your Azure account. You will also need to have Docker installed and running on your Jumpbox. Here are the steps to follow: \n   \n \n \n Select resource group rg-hub where the Jumpbox has been deployed. \n \n \n Within your resource group, find and click on the Jumpbox VM. \n \n \n In the left-hand side menu, under the Connect section, select ‘Bastion’. \n \n \n Enter the credentials for the Jumpbox VM and verify that you can log in successfully. \n \n \n Once successfully logged in to the jumpbox login to Azure if you have not already done so in previous steps. \n \n \n az login\n \n Identify your subscription id from the list, if you have several subscriptions. \n az account list -o table\n \n Set your subscription id to be the default subscription. \n az account set --subscription <SUBSCRIPTION ID>\n \n \n Validate private link connection. \n \n List your ACR in your subscription and note down the ACR name. \n az acr list -o table\n \n Example output: \n azureuser@Jumpbox-VM:~$ az acr list -o table\nNAME RESOURCE GROUP LOCATION SKU LOGIN SERVER CREATION DATE ADMIN ENABLED\n---------- ---------------- ---------- ------- --------------------- -------------------- ---------------\nalibaksacr rg-spoke eastus Premium alibaksacr.azurecr.io 2024-03-03T07:56:00Z False\n \n dig <REGISTRY NAME>.azurecr.io\n \n Example output shows the registry's private IP address in the address space of the subnet: \n \nazureuser@Jumpbox-VM:~$ dig alibaksacr.azurecr.io\n\n; <<>> DiG 9.18.18-0ubuntu0.22.04.2-Ubuntu <<>> alibaksacr.azurecr.io\n;; global options: +cmd\n;; Got answer:\n;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3738\n;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1\n\n;; OPT PSEUDOSECTION:\n; EDNS: version: 0, flags:; udp: 65494\n;; QUESTION SECTION:\n;alibaksacr.azurecr.io. IN A\n\n;; ANSWER SECTION:\nalibaksacr.azurecr.io. 60 IN CNAME alibaksacr.privatelink.azurecr.io.\nalibaksacr.privatelink.azurecr.io. 1800 IN A 10.1.1.21\n\n;; Query time: 8 msec\n;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)\n;; WHEN: Sun Mar 03 09:04:31 UTC 2024\n;; MSG SIZE rcvd: 103\n \n \n Test the connection to the container registry, you will push a container to it. You will need to create a Dockerfile, build the docker image, authenticate towards ACR and push the image to the container registry. \n \n vim Dockerfile\n \n Add the following content to the Dockerfile. \n FROM nginx\nEXPOSE 80\n \n Build the Docker image. \n docker build --tag nginx .\n \n Example output: \n azureuser@Jumpbox-VM:~$ docker build --tag nginx .\n\nSending build context to Docker daemon 222.7kB\nStep 1/3 : FROM nginx\nlatest: Pulling from library/nginx\na803e7c4b030: Pull complete \n8b625c47d697: Pull complete \n4d3239651a63: Pull complete \n0f816efa513d: Pull complete \n01d159b8db2f: Pull complete \n5fb9a81470f3: Pull complete \n9b1e1e7164db: Pull complete \nDigest: sha256:32da30332506740a2f7c34d5dc70467b7f14ec67d912703568daff790ab3f755\nStatus: Downloaded newer image for nginx:latest\n ---> 61395b4c586d\nStep 2/3 : EXPOSE 80\n ---> Running in d7267ee641b6\nRemoving intermediate container d7267ee641b6\n ---> 06a5ac2e4ba6\nStep 3/3 : CMD [“nginx”, “-g”, “daemon off;”]\n ---> Running in c02c94dc283c\nRemoving intermediate container c02c94dc283c\n ---> 49a47448ba86\nSuccessfully built 49a47448ba86\nSuccessfully tagged nginx:latest\n \n Create an alias of the image. \n docker tag nginx <CONTAINER REGISTRY NAME>.azurecr.io/nginx\n \n Authenticate to ACR with your AD user. \n az acr login --name <CONTAINER REGISTRY NAME> \n \n Upload the docker image to the ACR repository. \n docker push <CONTAINER REGISTRY NAME>.azurecr.io/nginx\n \n Example output: \n azureuser@Jumpbox-VM:~$ docker push acraksbl.azurecr.io/nginx\nUsing default tag: latest\nThe push refers to repository [acraksbl.azurecr.io/nginx]\nd26d4f0eb474: Pushed \na7e2a768c198: Pushed \n9c6261b5d198: Pushed \nea43d4f82a03: Pushed \n1dc45c680d0f: Pushed \neb7e3384f0ab: Pushed \nd310e774110a: Pushed \nlatest: digest: sha256:3dc6726adf74039f21eccf8f3b5de773080f8183545de5a235726132f70aba63 size: 1778\n \n \n To enable AKS to pull images from ACR, you can attach AKS to the ACR. This command updates the existing AKS cluster and attaches it to the ACR. \n \n az aks update \\\n --resource-group $SPOKE_RG \\\n --name $AKS_CLUSTER_NAME-${STUDENT_NAME} \\\n --attach-acr $ACR_NAME\n \n \n Validate AKS is able to pull images from ACR, by deploying a simple application to the AKS cluster. During deployment, the AKS cluster will pull the container image of the application from ACR. \n \n On the Jumpbox VM create a yaml file. \n vim test-pod.yaml\n \n Pro-tip: when you copy to vim, prevent vim from auto-indenting the text you paste. \n :set paste\n \n Press enter. \n Paste in the following manifest file which creates a pod named internal-test-app which fetches the docker images from our internal container registry, created in previous step. \n apiVersion: v1\nkind: Pod\nmetadata:\n name: internal-test-app\n labels:\n app: internal-test-app\nspec:\n containers:\n - name: nginx\n image: <ACR NAME>.azurecr.io/nginx\n ports:\n - containerPort: 80\n \n Create the pod. \n kubectl apply -f test-pod.yaml\n \n Verify that the pod is in running state. \n kubectl get po --show-labels\n \n Example output: \n azureuser@Jumpbox-VM:~$ kubectl get po \nNAME READY STATUS RESTARTS AGE\ninternal-test-app 1/1 Running 0 8s\n \n The next step is to set up an internal load balancer that will direct the traffic to our internal pod. The internal load balancer will be deployed in the load balancer subnet of the spoke-vnet. \n vim internal-app-service.yaml\n \n :set paste\n \n Press enter. \n Copy the following manifest to expose the pod to the internet. Replace with your subnet name stored in your local shell environment variable $LOADBALANCER_SUBNET_NAME. \n apiVersion: v1\nkind: Service\nmetadata:\n name: internal-test-app-service\n annotations:\n service.beta.kubernetes.io/azure-load-balancer-internal: \"true\"\n service.beta.kubernetes.io/azure-load-balancer-internal-subnet: \"<LOADBALANCER SUBNET NAME>\"\nspec:\n type: LoadBalancer\n ports:\n - port: 80\n selector:\n app: internal-test-app\n \n Deploy the service object in AKS. \n kubectl create -f internal-app-service.yaml\n \n Verify that your service object is created and associated with the pod that you have created, also ensure that you have recieved an external IP, which should be a private IP address range from the load balancer subnet. \n kubectl get svc -o wide\n \n Example output: \n azureuser@Jumpbox-VM:~$ kubectl get svc -o wide\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR\ninternal-test-app-service LoadBalancer 10.0.22.55 10.1.1.4 80:31644/TCP 112s app=internal-test-app\nkubernetes ClusterIP 10.0.0.1 <none> 443/TCP 13h <none>\n \n \n Note: Note down the EXTERNAL-IP (Private IP of the load balancer), as this will be used for creating the application gateway. \n \n   \n Verify that you are able to access the exposed Nginx pod from your jumpbox VM. \n azureuser@Jumpbox-VM:~$ curl <EXTERNAL-IP>\n \n Example output: \n azureuser@Jumpbox-VM:~$ curl 10.1.1.4\n<!DOCTYPE html>\n<html>\n<head>\n<title>Welcome to nginx!</title>\n<style>\nhtml { color-scheme: light dark; }\nbody { width: 35em; margin: 0 auto;\nfont-family: Tahoma, Verdana, Arial, sans-serif; }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n \n You have successfully deployed a private Azure Container Registry that is accessible from the jumpbox host. You also built and deployed the nginx image, which is only exposed over the private network. \n   \n \n   \n Deploy Azure Application Gateway. \n   \n In this section, you will set up an application gateway that will terminate TLS connections at its ingress. You will also learn how to perform these tasks: upload a certificate to Application Gateway, configure AKS as a backend pool by routing traffic to its internal load balancer, create a health probe to check the health of the AKS backend pool, and set up a WAF (Web Application Firewall) to defend against common web attacks. \n   \n \n Create public IP address with a domain name associated to the public IP resource. \n \n   \n The public IP address will be associated with a fully qualified domain name (FQDN) based on the location of your IP address and a unique name that you provide. For example, if you create an IP address in westeurope, the FQDN would look similar to this: \n myveryuniquename.westeurope.cloudapp.azure.com\n \n Lets make an environment variable of the uniqe name, and call it $DNS_NAME. \n DNS_NAME=<your unique name>\n \n az network public-ip create -g $SPOKE_RG -n AGPublicIPAddress --dns-name $DNS_NAME --allocation-method Static --sku Standard --location $LOCATION\n \n \n Create WAF policy. \n \n az network application-gateway waf-policy create --name ApplicationGatewayWAFPolicy --resource-group $SPOKE_RG\n \n \n Create self signed certificate. \n \n In order to expose your services to internet using HTTPs, you need to add a certificate to Application Gateway. In a production setting, this would be a trusted certificate from a certificate authority such as letsencrypt. In the interest of simplicity, you will instead create a self signed certificate, and upload to Application Gateway. \n Following are short instructions on how to create the self signed certificate. If you want to understand the details, or need more information, please review this page: https://learn.microsoft.com/en-us/azure/application-gateway/self-signed-certificates \n Step one is to create a Root CA Certificate. During the creation, you will need to provide an FQDN. This FQDN will be the one associated with the Public IP address created above. \n   \n To get the FQDN you can run the following command: \n az network public-ip show -g $SPOKE_RG -n AGPublicIPAddress --query dnsSettings.fqdn\n \n After this, use the following commands to create a key and sign the key (self signed). \n openssl genrsa -out my.key 2048\nopenssl req -new -x509 -sha256 -key my.key -out my.crt -days 365\n \n When prompted, type the password for the root key (and note it down), and the organizational information for the custom CA such as Country/Region, State, Org, OU, and the fully qualified domain name from the step above. Here is an example of how it might look: \n peter [ ~ ]$ openssl req -new -x509 -sha256 -key my.key -out my.crt -days 365\nYou are about to be asked to enter information that will be incorporated\ninto your certificate request.\nWhat you are about to enter is what is called a Distinguished Name or a DN.\nThere are quite a few fields but you can leave some blank\nFor some fields there will be a default value,\nIf you enter '.', the field will be left blank.\n-----\nCountry Name (2 letter code) [AU]:SE\nState or Province Name (full name) [Some-State]:\nLocality Name (eg, city) []:\nOrganization Name (eg, company) [Internet Widgits Pty Ltd]:\nOrganizational Unit Name (eg, section) []:\nCommon Name (e.g. server FQDN or YOUR name) []:uniqueappgwname.eastus.cloudapp.azure.com\nEmail Address []:johndoe@contoso.com\n \n Now, combine the private key and the certificate into a single .pfx file. Choose a good certificate password and make a note of it, as it will be used when creating the Application Gateway. \n openssl pkcs12 -export -out my.pfx -inkey my.key -in my.crt -password pass:<CERTIFICATE PASSWORD>\n \n \n Create Application Gateway. \n \n \n Note: Before executing the command below, make sure the certificate is located in your working directory. Replace with the password you used when creating the certificate and with the private IP of the load balancer. \n \n   \n az network application-gateway create \\\n --name AppGateway \\\n --location $LOCATION \\\n --resource-group $SPOKE_RG \\\n --vnet-name $SPOKE_VNET_NAME \\\n --subnet $APPGW_SUBNET_NAME \\\n --capacity 1 \\\n --sku WAF_v2 \\\n --http-settings-cookie-based-affinity Disabled \\\n --frontend-port 443 \\\n --http-settings-port 80 \\\n --http-settings-protocol Http \\\n --priority \"1\" \\\n --public-ip-address AGPublicIPAddress \\\n --cert-file my.pfx \\\n --cert-password \"<CERTIFICATE PASSWORD>\" \\\n --waf-policy ApplicationGatewayWAFPolicy \\\n --servers <LOAD BALANCER PRIVATE IP>\n \n \n Create a custom probe for the application gateway that will monitor the health of the AKS backend pool. \n \n az network application-gateway probe create \\\n --gateway-name $APPGW_NAME \\\n --resource-group $SPOKE_RG \\\n --name health-probe \\\n --protocol Http \\\n --path / \\\n --interval 30 \\\n --timeout 120 \\\n --threshold 3 \\\n --host 127.0.0.1\n \n \n Associate the health probe to the backend pool. \n \n az network application-gateway http-settings update -g $SPOKE_RG --gateway-name $APPGW_NAME -n appGatewayBackendHttpSettings --probe health-probe\n \n Validate your deployment in the Azure portal. \n \n \n Select the resource group called rg-spoke where the application gateway is deployed. \n \n \n Select your Azure Application Gateway called AppGateway. Ensure you have a Public IP address and Tier set to WAF v2. \n \n \n   \n \n \n \n In the left-hand side menu, under the Settings section, select Backend pools and choose from the list appGatewayBackendPool. \n \n \n Ensure the target type is set to IP address or FQDN and target is set to the IP address of your internal load balancer. \n \n \n   \n \n \n \n On the top menu click on AppGateway | Backend pools. \n \n \n Lets verify the backend settings of Application Gateway, in the left-hand side menu choose *Backend settings. \n \n \n From the list click on appGatewayBackendHttpSettings validate that the backend port is configured for port 80, and that health probe called health-probe is associated to the backend. \n \n \n   \n \n \n \n Press Cancel \n \n \n Verify that we have Web application rules configured. In the left-hand side menu choose *Web Application Firewall. \n \n \n Click on ApplicationGatewayWAFPolicy In the left-hand side menu choose *Managed rules. \n \n \n   \n \n We have successfully completed the deployment and configuration of the network and cluster resources. The following diagram shows the high-level architecture of the solution. As you can see, there is a test pod running in AKS that can receive traffic from the internet through the Azure Application Gateway and the Azure Internal Load Balancer. We can also access the private API server of the AKS cluster and the private container registry from the jumpbox using the private endpoints and links. We have also enabled outbound traffic from the AKS subnet to go through the Azure Firewall for inspection and filtering. In the next section, we will validate if we can access our test pod securely from the Internet. \n   \n \n   \n Validate Ingress Connection. \n   \n Open your web browser and access the domain created above: https://<application gateway FQDN> \n \n Note: The certificate used was self-signed, so the browser will issue a warning that the content is potentially unsafe. In a production setting, a certificate from a well known certificate authority should be used, but this is beyond the scope of this tutorial. \n \n   \n If you discard the warning, you should see a similar output as to the one below. \n   \n \n You have now verified connectivity from the public IP address, through the Application Gateway to the nginx pod running in your private AKS cluster. Well done! \n   \n Clean Up Resources in Azure \n   \n Once you have verified that everything works as depicted earlier you can issue the following commands to delete all of the Azure resources that you have created while working with these instructions.  The easiest way is to delete the resource groups which you have created your resources in. \n   \n az group delete -n $HUB_RG\naz group delete -n $SPOKE_RG \n   ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"62330","kudosSumWeight":8,"repliesCount":6,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00MTMwNDk2LTU3NzIxOGk0OTMwRTg3MjJEMjNERjdE?revision=11\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:3741548":{"__typename":"Conversation","id":"conversation:3741548","topic":{"__typename":"BlogTopicMessage","uid":3741548},"lastPostingActivityTime":"2023-04-26T13:34:26.500-07:00","solved":false},"User:user:24":{"__typename":"User","uid":24,"login":"jeffmedford","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS0yNC01NjI2aTg4RThGMzExM0YyQTY4OTA"},"id":"user:24"},"BlogTopicMessage:message:3741548":{"__typename":"BlogTopicMessage","subject":"A month of cloud native: Explore resources for cloud native app development","conversation":{"__ref":"Conversation:conversation:3741548"},"id":"message:3741548","revisionNum":2,"uid":3741548,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:24"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" For the month of May, we’re focusing on cloud native—a modern approach to development that leverages cloud technologies, like containers and microservices. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":32000},"postTime":"2023-04-26T13:34:26.500-07:00","lastPublishTime":"2023-04-26T13:34:26.500-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" For the month of May, we’re focusing on cloud native—a modern approach to development that leverages cloud technologies, like containers and microservices. By design, cloud-native applications offer many advantages, including easier scalability, improved resiliency, and simpler management. While it might sound like a major shift, adopting a cloud native strategy is easier and quicker than you might think. \n   \n To help you get started, we’ve gathered essential learning to help you embrace a cloud native approach. Learn the fundamentals, explore tools, work through guided samples, and join a live webinar to learn more about cloud native apps. \n   \n Cloud native fundamentals Start your cloud native journey. Find out what makes an app \"cloud native\" and learn about the core pillars of cloud native solutions. \n   \n Webinar: Building Sustainable Apps with Kubernetes Register now for this live webinar on May 16. Steven Murawski will discuss patterns and practices for building a sustainable workload on Kubernetes. \n   \n Containers 101 Containers are a key part of modernizing apps. Learn how they work, why they're good for development, and how they fit into your cloud native approach. \n   \n Ask the expert: Azure Kubernetes Service Have questions about Azure Kubernetes Service (AKS)? Watch this Ask the Expert session to hear Jorge Palma and Steven Murawski answer common questions from the community. Learn how to develop and secure Kubernetes clusters on Azure. \n   \n Microservices 101 Microservices improve development, deployment, and maintenance of your applications. Josh Duffney explores key technologies and gives tips on how to design a microservice.  \n     \n Kubernetes fundamentals – Pods and deployments Learn the fundamentals of Kubernetes. Steven Murawski breaks down pods and nodes, and shares detailed steps for setting up an AKS environment.  \n   \n Kubernetes fundamentals – Services and Ingress Ready to share your apps with the world? Paul Yu details how to make your containers accessible using Services and Ingress. \n   \n Kubernetes fundamentals – ConfigMaps and Secrets Learn a best practice that will help improve the scalability and security of your cluster. Find out how to decouple configuration data and sensitive information from your pod definitions. \n     \n Kubernetes fundamentals – Volumes, mounts, and claims Containers are built to start with a clean slate. Find out how you can ensure your data isn’t lost when a container crashes or restarts. Paul Yu explains how to use persistent storage on Kubernetes and AKS. \n       \n Kubernetes fundamentals – Scaling pods and nodes A major advantage to using Kubernetes is the ability to scale. Check out this detailed step-by-step look at how to scale pods and nodes in an AKS cluster. \n   \n Bringing your application to Kubernetes – CI/CD Ready to move an existing app to Kubernetes? Get your CI/CD process ready. Step through the process of how to bring an app to AKS with a full pipeline in GitHub Actions. \n   \n Introduction to cloud-native apps on Azure Are you new to cloud native apps? Start from the beginning with this free training from Microsoft Learn. Quickly explore core concepts and technologies, and find out why and when you should build cloud-native apps. \n      \n Serverless container options There are many serverless container options. Choosing the right path can be daunting. Here’s a breakdown of options on Azure and considerations that will help you decide which solutions are right for your application.  \n   \n Jump start your applications with Draft Your journey from code to Kubernetes will be a lot easier with Draft.  Cory Skimming covers the basics of this open-source tool. Discover how Draft offers a simple way to create and deploy applications to Kubernetes. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3950","kudosSumWeight":3,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:2867959":{"__typename":"Conversation","id":"conversation:2867959","topic":{"__typename":"BlogTopicMessage","uid":2867959},"lastPostingActivityTime":"2021-11-03T01:50:19.366-07:00","solved":false},"User:user:1096440":{"__typename":"User","uid":1096440,"login":"Hanli_Ren","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/m_assets/avatars/default/avatar-12.svg?time=0"},"id":"user:1096440"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxOTIwNmkzQTg2MEFEOEMzQ0Y1QzVG?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxOTIwNmkzQTg2MEFEOEMzQ0Y1QzVG?revision=12","title":"Hanli_Ren_0-1634885022054.png","associationType":"BODY","width":1500,"height":430,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3M2kwMjFDMzNCMDY4NjlGNjI3?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3M2kwMjFDMzNCMDY4NjlGNjI3?revision=12","title":"Hanli_Ren_0-1634796508268.png","associationType":"BODY","width":1664,"height":1679,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3NGk3OTJENDIxOUIxMkY1REE1?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3NGk3OTJENDIxOUIxMkY1REE1?revision=12","title":"Hanli_Ren_1-1634796583600.png","associationType":"BODY","width":1763,"height":728,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3N2lFRjhCRUNDOEM1NUREMTg5?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3N2lFRjhCRUNDOEM1NUREMTg5?revision=12","title":"Hanli_Ren_2-1634797314255.png","associationType":"BODY","width":2000,"height":429,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4MGlENkNEM0ZGOTFFMDUyQkI2?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4MGlENkNEM0ZGOTFFMDUyQkI2?revision=12","title":"Hanli_Ren_3-1634797974310.png","associationType":"BODY","width":1422,"height":420,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4MWlCRUY4RUEzM0U2MThCRkIw?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4MWlCRUY4RUEzM0U2MThCRkIw?revision=12","title":"Hanli_Ren_4-1634798041950.png","associationType":"BODY","width":1851,"height":924,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NGkxQUZBOEVEOUUxQjNBODIw?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NGkxQUZBOEVEOUUxQjNBODIw?revision=12","title":"Hanli_Ren_5-1634798335934.png","associationType":"BODY","width":2000,"height":887,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NWk4Njk1Qjk5MUU2MkE3NTVF?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NWk4Njk1Qjk5MUU2MkE3NTVF?revision=12","title":"Hanli_Ren_6-1634798813257.png","associationType":"BODY","width":1364,"height":242,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NmkyNEEwNTU0QTVBNDJDRjUy?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NmkyNEEwNTU0QTVBNDJDRjUy?revision=12","title":"Hanli_Ren_7-1634798904178.png","associationType":"BODY","width":1897,"height":956,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4N2lGQTU5MjBCMEY3MERBOENF?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4N2lGQTU5MjBCMEY3MERBOENF?revision=12","title":"Hanli_Ren_8-1634800322047.png","associationType":"BODY","width":2000,"height":889,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5MmlDQzIwN0YwODkyMTZGRjU4?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5MmlDQzIwN0YwODkyMTZGRjU4?revision=12","title":"Hanli_Ren_9-1634800717288.png","associationType":"BODY","width":2000,"height":561,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5M2k4M0Y1RUNDMjE3Qjc0RjJE?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5M2k4M0Y1RUNDMjE3Qjc0RjJE?revision=12","title":"Hanli_Ren_10-1634800755358.png","associationType":"BODY","width":1008,"height":579,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5NGlCNjA5Qjc3MEE0MTZGNzlC?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5NGlCNjA5Qjc3MEE0MTZGNzlC?revision=12","title":"Hanli_Ren_11-1634800773668.png","associationType":"BODY","width":1964,"height":951,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5NmkxMTU1RTUyMjE4NDRBQzRD?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5NmkxMTU1RTUyMjE4NDRBQzRD?revision=12","title":"Hanli_Ren_0-1634802073997.png","associationType":"BODY","width":1432,"height":744,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5N2lGNUQ4RDcxMkY5QkZFQzkz?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5N2lGNUQ4RDcxMkY5QkZFQzkz?revision=12","title":"Hanli_Ren_1-1634802212597.png","associationType":"BODY","width":1889,"height":812,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5OWk2MEYyNTkzQjA0QzEwQkI4?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5OWk2MEYyNTkzQjA0QzEwQkI4?revision=12","title":"Hanli_Ren_2-1634802312009.png","associationType":"BODY","width":745,"height":645,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODkwMGk3REVDRThCMzUwNjFBQ0Yw?revision=12\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODkwMGk3REVDRThCMzUwNjFBQ0Yw?revision=12","title":"Hanli_Ren_3-1634802383930.png","associationType":"BODY","width":863,"height":385,"altText":null},"BlogTopicMessage:message:2867959":{"__typename":"BlogTopicMessage","subject":"App Service on Kubernetes with Azure Arc","conversation":{"__ref":"Conversation:conversation:2867959"},"id":"message:2867959","revisionNum":12,"uid":2867959,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:1096440"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":26400},"postTime":"2021-11-02T22:23:25.423-07:00","lastPublishTime":"2021-11-02T22:23:25.423-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" We are happy to introduce this Preview feature that allows App Service running on Kubernetes or anywhere with Azure Arc. \n   \n Azure Arc allows you to deploy Azure application services such as Azure App Service, Functions, Logic Apps, Event Grid, and API Management anywhere, on-premises, edge locations, or any other cloud provider. This is great if you are building and running cloud-native applications on Azure PaaS services and want them to run outside of Azure without rearchitecting them. \n   \n In this blog, we will demonstrate an example of how to setup an App Service running on AKS from scratch. \n   \n Main reference documents used by this blog are: - Set up Azure Arc for App Service, Functions, and Logic Apps  - Quickstart: Create a web app on Azure Arc  \n   \n The complete steps can be separated into 4 parts: \n \n Part 1: Prepare the AKS and Azure Arc environment \n Part 2: Create Azure App Service in Kubernetes cluster \n Part 3: Deploy Application Code \n Part 4: Basic methods that can help you do the monitoring and troubleshooting \n \n   \n Part 1: Prepare the AKS and Azure Arc environment \n In this part, I will only list all the bash commands that used to create AKS, Azure Arc, customer location, etc. These can be a quick reference when you need to create these resources from scratch. \n More detailed explanations and command usage details can be found in https://docs.microsoft.com/en-us/azure/app-service/manage-create-arc-environment?tabs=bash  \n   \n The following Bash commands can be executed inside Azure Cloud Shell. \n \n You can also install Azure CLI (version >= 2.26.0) in your local machine and run the Bash commands locally.  \n Note: usually Linux OS by default has bash installed. For Windows OS, you may consider using WSL or Cygwin. \n   \n Install Azure CLI extensions \n Because these CLI commands are not part of the core CLI set, we need to add them with the following commands. \n   \n az extension add --upgrade --yes --name connectedk8s\naz extension add --upgrade --yes --name k8s-extension\naz extension add --upgrade --yes --name customlocation\naz provider register --namespace Microsoft.ExtendedLocation --wait\naz provider register --namespace Microsoft.KubernetesConfiguration --wait\naz provider register --namespace Microsoft.Kubernetes --wait\naz provider register --namespace Microsoft.Web --wait\naz extension remove --name appservice-kube\naz extension add --yes --source \"https://aka.ms/appsvc/appservice_kube-latest-py2.py3-none-any.whl\"\n \n   \n   \n Create a connected cluster \n We will use this new created AKS cluster to deploy your App Service. If you already has an existing ASK cluster, then you can skip this step and continue to \"Connect the cluster to Azure Arc\" step. \n   \n aksClusterGroupName=\"<Define your AKS Resource Group name>\" # Name of resource group for the AKS cluster\naksName=\"${aksClusterGroupName}-aks\" # Name of the AKS cluster\nresourceLocation=\"<Define your preferred location>\" # \"eastus\" or \"westeurope\" (in Preview stage, only these two locations are supported now)\n\t\naz group create -g $aksClusterGroupName -l $resourceLocation\naz aks create --resource-group $aksClusterGroupName --name $aksName --enable-aad --generate-ssh-keys\ninfra_rg=$(az aks show --resource-group $aksClusterGroupName --name $aksName --output tsv --query nodeResourceGroup)\naz network public-ip create --resource-group $infra_rg --name MyPublicIP --sku STANDARD\nstaticIp=$(az network public-ip show --resource-group $infra_rg --name MyPublicIP --output tsv --query ipAddress)\n\t\naz aks get-credentials --resource-group $aksClusterGroupName --name $aksName --admin\nkubectl get ns\n\t\n \n   \n   \n Connect the AKS cluster to Azure Arc \n Connect the cluster you created to Azure Arc. \n   \n groupName=\"<Define your Azure Arc Group name>\" # Name of resource group for your Azure Arc resource\naz group create -g $groupName -l $resourceLocation\n\t\nclusterName=\"${groupName}-cluster\" # Name of the connected cluster resource\naz connectedk8s connect --resource-group $groupName --name $clusterName\naz connectedk8s show --resource-group $groupName --name $clusterName \n   \n   \n Create a Log Analytics workspace \n While a Log Analytic workspace is not required to run App Service in Azure Arc, it's how developers can get application logs for their apps that are running in the Azure Arc-enabled Kubernetes cluster. \n   \n workspaceName=\"$groupName-workspace\" # Name of the Log Analytics workspace\n\naz monitor log-analytics workspace create \\\n\t --resource-group $groupName \\\n\t --workspace-name $workspaceName\n\t\nlogAnalyticsWorkspaceId=$(az monitor log-analytics workspace show \\\n\t --resource-group $groupName \\\n\t --workspace-name $workspaceName \\\n\t --query customerId \\\n\t --output tsv)\n\t\nlogAnalyticsWorkspaceIdEnc=$(printf %s $logAnalyticsWorkspaceId | base64 -w0) # Needed for the next step\n\t\nlogAnalyticsKey=$(az monitor log-analytics workspace get-shared-keys \\\n\t --resource-group $groupName \\\n\t --workspace-name $workspaceName \\\n\t --query primarySharedKey \\\n\t --output tsv)\n\t\nlogAnalyticsKeyEnc=$(printf %s $logAnalyticsKey | base64 -w0) # Needed for the next step \n   \n   \n Install the App Service extension \n Install the require App Service extension in the Azure Arc. \n   \n extensionName=\"appservice-ext\" # Name of the App Service extension\nnamespace=\"appservice-ns\" # Namespace in your cluster to install the extension and provision resources\nkubeEnvironmentName=\"<Define your AppService Kubernetes Environment Name>\" # Name of the App Service Kubernetes environment resource\n\t\naz k8s-extension create \\\n --resource-group $groupName \\\n --name $extensionName \\\n --cluster-type connectedClusters \\\n --cluster-name $clusterName \\\n --extension-type 'Microsoft.Web.Appservice' \\\n --release-train stable \\\n --auto-upgrade-minor-version true \\\n --scope cluster \\\n --release-namespace $namespace \\\n --configuration-settings \"Microsoft.CustomLocation.ServiceAccount=default\" \\\n --configuration-settings \"appsNamespace=${namespace}\" \\\n --configuration-settings \"clusterName=${kubeEnvironmentName}\" \\\n --configuration-settings \"loadBalancerIp=${staticIp}\" \\\n --configuration-settings \"keda.enabled=true\" \\\n --configuration-settings \"buildService.storageClassName=default\" \\\n --configuration-settings \"buildService.storageAccessMode=ReadWriteOnce\" \\\n --configuration-settings \"customConfigMap=${namespace}/kube-environment-config\" \\\n --configuration-settings \"envoy.annotations.service.beta.kubernetes.io/azure-load-balancer-resource-group=${aksClusterGroupName}\" \\\n --configuration-settings \"logProcessor.appLogs.destination=log-analytics\" \\\n --configuration-protected-settings \"logProcessor.appLogs.logAnalyticsConfig.customerId=${logAnalyticsWorkspaceIdEnc}\" \\\n --configuration-protected-settings \"logProcessor.appLogs.logAnalyticsConfig.sharedKey=${logAnalyticsKeyEnc}\"\n\t\nextensionId=$(az k8s-extension show \\\n\t --cluster-type connectedClusters \\\n\t --cluster-name $clusterName \\\n\t --resource-group $groupName \\\n\t --name $extensionName \\\n\t --query id \\\n\t --output tsv)\n\t\naz resource wait --ids $extensionId --custom \"properties.installState!='Pending'\" --api-version \"2020-07-01-preview\"\n\t\nkubectl get pods -n $namespace \n   \n   \n Create a custom location \n Create your custom location in Azure, it will be used to assign the App Service Kubernetes environment. \n   \n customLocationName=\"<Define your custom location name>\" # Name of the custom location\n\t\nconnectedClusterId=$(az connectedk8s show --resource-group $groupName --name $clusterName --query id --output tsv)\n\t\naz customlocation create \\\n --resource-group $groupName \\\n --name $customLocationName \\\n --host-resource-id $connectedClusterId \\\n --namespace $namespace \\\n --cluster-extension-ids $extensionId\n\t\naz customlocation show --resource-group $groupName --name $customLocationName\n\t\ncustomLocationId=$(az customlocation show \\\n --resource-group $groupName \\\n --name $customLocationName \\\n --query id \\\n --output tsv) \n   \n Record your customLocationId, which will be used when you create your App Service in the later step. \n   \n echo $customLocationId \n   \n You will get result like this: \n /subscriptions/<subscript_id>/resourcegroups/<resource-group-name>/providers/microsoft.extendedlocation/customlocations/<customLocationName> \n   \n Create the App Service Kubernetes environment \n The App Service Kubernetes environment resource is required before apps may be created. It enables configuration common to apps in the custom location, such as the default DNS suffix. \n   \n az appservice kube create \\\n --resource-group $groupName \\\n --name $kubeEnvironmentName \\\n --custom-location $customLocationId \\\n --static-ip $staticIp\n\t\naz appservice kube show --resource-group $groupName --name $kubeEnvironmentName \n   \n   \n Part 2: Create Azure App Service in Kubernetes cluster \n We can use either Azure CLI or Azure Portal to create App Service in the Kubernetes cluster. \n Option 1: Use Azure CLI command to create App Service in your custom location \n Create App Service Plan: \n   \n az appservice plan create -g <Define your App Service Resource Group name> -n <Define your App Service Plan name> \\\n --custom-location $customLocationId \\\n --per-site-scaling --is-linux --sku K1 \n   \n   \n Create App Service using built-in Runtime stack: \n To see all supported runtimes, run \"az webapp list-runtimes --linux\". \n   \n az webapp create \\\n --plan <your App Service Plan name> \\\n --resource-group <your App Service Resource Group name> \\\n --name <Define your App Service name> \\\n --custom-location $customLocationId \\\n --runtime 'python|3.8'\n \n   \n   \n Create App Service using your own Custom docker image: \n   \n az webapp create \\\n --plan <your App Service Plan name> \\\n --resource-group <your App Service Resource Group name> \\\n --name <Define your App Service name> \\\n --custom-location $customLocationId \\\n --deployment-container-image-name <your ACR name>.azurecr.io/<image-name>:<tag>\n \n   \n   \n Option 2:  Use Azure Portal to create App Service in your custom location \n Create a resource > Marketplace > Web App  \n \n We can choose to use App Service built-in Runtime stack or your own Docker Container. \n \n   \n Part 3: Deploy Application Code \n If you are deploying your Custom Docker Image to App Service, there is no need to deploy application code separately. Since all the application code should already be packed inside your docker image. \n If you are using App Service built-in Runtime stack, since the built-in docker image won't include your application code, you will need to deploy your code to the App Service. One of the easiest ways to deploy your code is using zip deployment. \n   \n Node.js deployment example \n Your can pack your Node.js application on your local machine using the same Node.js version as you choose when creating the App Service. As an example, we can start from the following sample code: \n   \n git clone https://github.com/Azure-Samples/nodejs-docs-hello-world \n   \n In order to test dependency package installation, you can define your own \"dependencies\" section in package.json file. \n For example: \n   \n {\n \"name\": \"app-service-hello-world\",\n \"description\": \"Simple Hello World Node.js sample for Azure App Service\",\n \"version\": \"0.0.1\",\n \"private\": true,\n \"license\": \"MIT\",\n \"author\": \"Microsoft\",\n \"scripts\": {\n \"start\": \"node index.js\"\n },\n \"dependencies\": {\n \"http-errors\": \"~1.6.3\",\n \"applicationinsights\": \"1.8.7\"\n }\n} \n   \n Then use the following commands to pack the application into package.zip file. Make sure you run the \"npm install\" command, then confirm packages being installed in node_modules folder. \n   \n cd nodejs-docs-hello-world\nnpm install\nzip -r package.zip . \n   \n Deploy the zip file to the App Service. \n   \n az webapp deployment source config-zip --resource-group <your App Service Resource Group name> --name <your App Service Name> --src package.zip\n \n   \n   \n Python deployment example \n Your can pack your python application on your local machine using the same Python version as you choose when creating the App Service. As an example, we can start from the following sample code: \n   \n git clone https://github.com/Azure-Samples/python-docs-hello-world \n   \n In order to test dependency package installation, you can add packages in your requirements.txt file Then use the following commands to pack the application into package.zip file. Make sure you create a python virtual environment with name \"antenv\", then run the \"pip install\" command and confirm packages being installed in /antenv/lib/pythonx.x/site-packages/. \n   \n cd python-docs-hello-world/\npython3 -m venv antenv\nsource antenv/bin/activate\npip install -r requirements.txt\nzip -r package.zip .\n \n   \n   \n Deploy the zip file to the App Service. \n   \n az webapp deployment source config-zip --resource-group <your App Service Resource Group name> --name <your App Service Name> --src package.zip \n   \n   \n After the code being successfully deployed, you should be able to open the website using the URL showed up in the App Service Overview Portal. \n \n   \n   \n Part 4: Basic methods that can help you do the monitoring and troubleshooting \n Use kubectl command to monitor and troubleshoot your AKS cluster \n You can run kubectl command in Azure Cloud Shell, or you can run it on your local machine with Azure CLI installed.  \n Firstly, your will need to get kubeconfig file and test your connection to the cluster. By default, the kubeconfig file is saved to ~/.kube/config. \n   \n az aks get-credentials --resource-group <your AKS Resource Group name> --name <your aks cluster name> --admin\n \n   \n \n   \n Check pods status in your AKS. \n The namespace value should be the one you defined in Part 1: Install the App Service extension step. \n   \n kubectl get pods --namespace appservice-ns \n   \n \n   \n Check App Service pod log. \n The App Service pod name is listed by \"kubectl get pods ...\" command. \n   \n kubectl --namespace appservice-ns logs <App Service pod name> \n   \n \n   \n Get AKS node status \n   \n kubectl get nodes \n   \n \n   \n Get node details \n   \n kubectl describe node aks-nodepool1-xxxx-xxxx \n   \n \n   \n Manually scale the node count \n The \"resource group name\" should be \"aksClusterGroupName\" value you defined in Part 1: Create a connected cluster step. \n The \"AKS cluster name\" should be \"aksName\" value you defined in Part 1: Create a connected cluster step. \n   \n az aks scale --resource-group <your AKS cluser resource group> --name <your AKS cluster name> --node-count 3 \n   \n   \n Restart the AKS cluster \n   \n az aks stop --name <your AKS cluster name> --resource-group <your AKS cluster resource group>\naz aks start --name <your AKS cluster name> --resource-group <your AKS cluster resource group> \n   \n   \n Check Logs in Log Analytics Workspace \n App Service docker console logs are also recorded in the Log Analytics Workspace we created in Part 1: Create a Log Analytics workspace step. \n You can use the following Kusto query to get logs generated by a specific App Service. \n   \n AppServiceConsoleLogs_CL \n| where AppName_s == \"<App Service Name>\"\n| project TimeGenerated,AppName_s, ContainerImage_s,Log_s\n \n   \n   \n \n   \n Use WebSSH to access App Service application docker container \n If you are using App Service Built-in runtime. The docker image already has WEBSSH enabled. So you can login to your application docker container. Get the App Service's scm site URL, user name and password in App Service Portal --> Overview --> Get publish profile \n \n Go to https://<app-service-name>.scm.xxxxxx.xxxx.k4apps.io/instances/any/webssh/host Put in username and password you got in publish profile file. \n \n Then you should be able to log in to the Application Docker Container via WEBSSH. \n \n   \n Access the Kubernetes web dashboard in Azure Kubernetes Service (AKS) \n Reference doc: \n https://docs.microsoft.com/en-us/azure/aks/kubernetes-dashboard#for-rbac-enabled-clusters \n https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/ \n   \n You need the Azure CLI version 2.6.0 or later installed and configured on your local machine. \n   \n Get the admin kubeconfig with the following command: \n The RG_NAME should be \"aksClusterGroupName\" value you defined in Part 1: Create a connected cluster step. \n The CLUSTER_NAME should be \"aksName\" value you defined in Part 1: Create a connected cluster step. \n configure file by defualt will be saved in ~/.kube/config \n   \n az aks get-credentials -a --resource-group <RG_NAME> --name <CLUSTER_NAME> \n   \n   \n The Kubernetes Dashboard UI is not deployed by default. To deploy it, run the following command: \n   \n kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml \n   \n   \n You can enable access to the Dashboard using the kubectl command-line tool, by running the following command: \n   \n kubectl proxy \n   \n   \n Then you can access Kubernetes dashboard in your local machine. \n http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login  \n   \n We can check App Service details in the dashboard. \n \n For example: \n Check Docker container logs. \n \n Get inside the Docker container \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"18266","kudosSumWeight":3,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxOTIwNmkzQTg2MEFEOEMzQ0Y1QzVG?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3M2kwMjFDMzNCMDY4NjlGNjI3?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3NGk3OTJENDIxOUIxMkY1REE1?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg3N2lFRjhCRUNDOEM1NUREMTg5?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4MGlENkNEM0ZGOTFFMDUyQkI2?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4MWlCRUY4RUEzM0U2MThCRkIw?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDc","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NGkxQUZBOEVEOUUxQjNBODIw?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDg","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NWk4Njk1Qjk5MUU2MkE3NTVF?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDk","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4NmkyNEEwNTU0QTVBNDJDRjUy?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEw","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg4N2lGQTU5MjBCMEY3MERBOENF?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEx","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5MmlDQzIwN0YwODkyMTZGRjU4?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEy","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5M2k4M0Y1RUNDMjE3Qjc0RjJE?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEz","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5NGlCNjA5Qjc3MEE0MTZGNzlC?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE0","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5NmkxMTU1RTUyMjE4NDRBQzRD?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE1","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5N2lGNUQ4RDcxMkY5QkZFQzkz?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE2","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODg5OWk2MEYyNTkzQjA0QzEwQkI4?revision=12\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE3","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0yODY3OTU5LTMxODkwMGk3REVDRThCMzUwNjFBQ0Yw?revision=12\"}"}}],"totalCount":17,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:3247956":{"__typename":"Conversation","id":"conversation:3247956","topic":{"__typename":"BlogTopicMessage","uid":3247956},"lastPostingActivityTime":"2022-05-29T23:13:33.360-07:00","solved":false},"User:user:1229099":{"__typename":"User","uid":1229099,"login":"aaron-w","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS0xMjI5MDk5LTMzMDI2NmkxMjQ5MTEyRTY5OEE4NzBD"},"id":"user:1229099"},"BlogTopicMessage:message:3247956":{"__typename":"BlogTopicMessage","subject":"Run scalable and resilient Redis with Kubernetes and Azure Kubernetes Service","conversation":{"__ref":"Conversation:conversation:3247956"},"id":"message:3247956","revisionNum":7,"uid":3247956,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:1229099"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" \n In this post we show you how we can deploy a highly available Redis Cluster to Kubernetes and explore it using the Redis CLI, Python and Go (golang). \n ","introduction":"","metrics":{"__typename":"MessageMetrics","views":24900},"postTime":"2022-03-04T14:59:46.173-08:00","lastPublishTime":"2022-03-04T17:56:00.658-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n Redis is a successful open source in-memory data structure store first released in 2009. It is most commonly used as a database, cache, and message broker. Developers enjoy Redis for its versatility and simplicity. Low cognitive load makes development fast and efficient. \n   \n Language support for Redis is very mature with https://redis.io/clients across every major language one might expect, with multiple community-supported implementations per language (including Go, Java, Python and Rust), as well as support for advanced functionality such as Redis Cluster and Redis Sentinel, which enable sharding and master-replica topologies respectively. \n   \n Many other open source projects integrate with Redis. Just two examples in the cloud native ecosystem that we contribute to in the CNCF are https://dapr.io/ and https://keda.sh/. Dapr supports Redis for both its https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-redis/ and https://docs.dapr.io/reference/components-reference/supported-pubsub/setup-redis-pubsub/ components, and Redis is used by default for local development. KEDA has https://keda.sh/docs/2.6/scalers/ for Redis that support Redis Lists and Redis Streams, including support for Redis Cluster and Redis Sentinel. \n   \n Why run Redis containerized, or on Kubernetes? \n Redis is fully supported by managed cloud services such as https://docs.microsoft.com/en-us/azure/azure-cache-for-redis/cache-overview which are often the first choice for customers deploying Redis open-source and Redis Enterprise in the cloud. \n   \n However, there are many valid reasons developers choose to deploy their own instances of Redis. Linux is the recommended deployment platform, and Docker is a seamless, cross-platform, option to run Redis locally for development purposes. Redis is especially popular on container-oriented cloud native platforms such as Kubernetes, including managed platforms such as https://docs.microsoft.com/en-us/azure/aks/intro-kubernetes. Common reasons to deploy Redis using Docker or Kubernetes include: \n   \n \n Portability – developers may want a truly vendor agnostic solution. An open source application, for example, can be packaged into a helm chart and be a single https://helm.sh/docs/helm/helm_install/ away, on any Kubernetes cluster, anywhere. \n Local development – Whether using https://hub.docker.com/r/bitnami/redis, or https://github.com/kubernetes-sigs/kind, the benefits of a local, containerized, development environment which closely mirrors a production environment in the cloud can be significant. \n Scalability – Rather than remain static, it may make sense for Redis to scale with your application. Whether as a side-car cache to specific components of your application, or scaled in-cluster with the https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ Pod Autoscaler, Kubernetes is often a great choice for scalable compute. \n Monitoring – Kubernetes has a rich observability ecosystem and the ability to monitor Redis with tools like Prometheus and Grafana is no exception. \n \n Resilient and highly-available Redis \n While Kubernetes can help make Redis more resilient – even a self-healing singleton Kubernetes service can be better than a stand-alone virtual machine – true high-availability is often desirable. For example, if you are using Redis as a cache, your application may be able to survive the temporary unavailability of Redis under modest load. However, under significant load, the loss of a cache may cause the application to fail. \n   \n In this post we explore how we can deploy a highly available Redis Cluster to Kubernetes. \n   \n Deploy AKS \n In this post we will be using Azure Kubernetes Service (AKS) cluster which we will https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough#connect-to-the-cluster. Make sure you have the https://docs.microsoft.com/en-us/cli/azure/install-azure-cli before you continue. \n   \n Create a Resource Group \n az group create --name my-aks \\\n --location eastus\n \n Create an AKS cluster \n az aks create --resource-group my-aks \\\n --name aks1 \\\n --node-count 3 \\\n --enable-addons monitoring \\\n --generate-ssh-keys\n \n Install kubectl if you do not have it installed already \n az aks install-cli\n \n Configure kubectl to authenticate to your cluster \n az aks get-credentials --resource-group my-aks \\\n --name aks1\n \n   \n Deploy Redis Cluster using the Bitnami Helm chart repository \n Helm is the easiest way to deploy complex applications to Kubernetes. Bitnami provides helm charts for Redis as part of its https://docs.bitnami.com/kubernetes/apps/ which are fully https://docs.bitnami.com/kubernetes/get-started-aks/, and https://github.com/bitnami/charts. \n   \n Redis™ Cluster Packaged By Bitnami For Kubernetes provides https://docs.bitnami.com/kubernetes/infrastructure/redis-cluster/get-started/compare-solutions/ns for deploying a production-grade Redis deployment on Kubernetes. Redis Cluster enables sharing and disaster recovery, but supports a single database, and Redis Sentinel uses a master-replica, with a single master, and supports multiple databases. You can read more about replication https://redis.io/topics/replication. Let’s install it. \n   \n Add the bitnami helm chart repository. \n helm repo add bitnami https://charts.bitnami.com/bitnami\n \n Install the redis-cluster helm chart. \n helm install my-redis bitnami/redis-cluster\n \n You will be prompted to set a REDIS_PASSWORD environment variable extracted from the Kubernetes secret. Note this is a bash environment variable (use via Windows System for Linux/macOS/Linux, etc). If you use another shell, adjust the syntax accordingly. \n export REDIS_PASSWORD=$(kubectl get secret --namespace \"default\" my-redis-redis-cluster -o jsonpath=\"{.data.redis-password}\" | base64 --decode)\n \n   \n Explore with redis-cli \n Run a pod inside the cluster that will enable us to connect to Redis using the REDIS_PASSWORD environment variable you set earlier. \n kubectl run --namespace default my-redis-redis-cluster-client \\\n --rm --tty -i --restart='Never' \\\n --env REDIS_PASSWORD=$REDIS_PASSWORD \\\n --image docker.io/bitnami/redis-cluster:6.2.6-debian-10-r137 -- bash\n \n Connect to the Redis cluster using redis-cli . Note that the -c switch is required when connecting to a cluster. \n redis-cli -c -h my-redis-redis-cluster -a $REDIS_PASSWORD\n \n Next run four set commands from the CLI: \n set one hello\nset two world\nset three goodbye\nset four world\n \n You will see output that indicates the client is being redirected to multiple nodes. \n 10.244.0.6:6379> set one hello\n-> Redirected to slot [9084] located at 10.244.1.5:6379\nOK\n10.244.1.5:6379> set two world\n-> Redirected to slot [2127] located at 10.244.0.6:6379\nOK\n10.244.0.6:6379> set three goodbye\n-> Redirected to slot [13861] located at 10.244.2.7:6379\nOK\n10.244.2.7:6379> set four world\n-> Redirected to slot [8296] located at 10.244.1.5:6379\nOK\n \n The same will apply when you get the values. \n get one\nget two\nget three\nget four\n \n For a deeper dive into the functionality, Redis has an excellent https://redis.io/topics/cluster-tutorial which can you follow from the https://redis.io/topics/cluster-tutorial#:~:text=Playing%20with%20the%20cluster section. It includes sections on Writing an example app with redis-rb-cluster, Resharding the cluster, Scripting a resharding operation, A more interesting example application (with consistency-test.rb), and Testing the failover. \n   \n When testing a failover, choose a pod to delete. \n kubectl get pods\n \n You will see the pods as follows. \n NAME READY STATUS RESTARTS AGE\nmy-redis-redis-cluster-0 1/1 Running 0 33m\nmy-redis-redis-cluster-1 1/1 Running 0 33m\nmy-redis-redis-cluster-2 1/1 Running 0 33m\nmy-redis-redis-cluster-3 1/1 Running 0 33m\nmy-redis-redis-cluster-4 1/1 Running 0 33m\nmy-redis-redis-cluster-5 1/1 Running 0 33m\nmy-redis-redis-cluster-client 1/1 Running 0 25m\n \n Then delete a pod. It will be automatically re-created and you will see its status as ContainerCreating . \n kubectl delete pod my-redis-redis-cluster-3\n \n Next, we will connect to our cluster with Python and Go. \n   \n Explore with Python \n The official Redis client for Python, https://github.com/redis/redis-py, now supports Redis Cluster. Previously Python users might have had experience with https://github.com/Grokzen/redis-py-cluster which the official library’s support https://github.com/Grokzen/redis-py-cluster, with the original repo becoming a “laboratory for redis and cluster moving forward”. \n   \n Open a new terminal and set the REDIS_PASSWORD environment variable. \n export REDIS_PASSWORD=$(kubectl get secret --namespace \"default\" my-redis-redis-cluster -o jsonpath=\"{.data.redis-password}\" | base64 --decode)\n \n Run a https://hub.docker.com/_/python container interactively. \n kubectl run --namespace default python-redis-cluster-test \\\n --rm --tty -i --restart='Never' \\\n --env REDIS_PASSWORD=$REDIS_PASSWORD \\\n --image python -- bash\n \n Install the official https://github.com/redis/redis-py package using pip. \n pip install redis\n \n Run python in interactive mode. \n python\n \n Paste the following snippet at the prompt ( >>> ). \n from redis.cluster import RedisCluster as Redis\nimport os\n\nREDIS_CLUSTER_NAME=\"my-redis-redis-cluster\"\nREDIS_CLUSTER_PORT=6379\nREDIS_CLUSTER_PASSWORD=os.getenv('REDIS_PASSWORD')\n\nfrom redis.cluster import RedisCluster as Redis\nrc = Redis(host=REDIS_CLUSTER_NAME, port=REDIS_CLUSTER_PORT, password=REDIS_CLUSTER_PASSWORD)\n \n Now you have a fully authenticated client, rc . \n   \n Output the nodes. \n rc.get_nodes()\n \n You will see the nodes listed as follows. \n >>> rc.get_nodes()\n[[host=10.244.0.6,port=6379,name=10.244.0.6:6379,server_type=primary,redis_connection=Redis<ConnectionPool<Connection<host=10.244.0.6,port=6379,db=0>>>], [host=10.244.2.8,port=6379,name=10.244.2.8:6379,server_type=replica,redis_connection=Redis<ConnectionPool<Connection<host=10.244.2.8,port=6379,db=0>>>], [host=10.244.1.5,port=6379,name=10.244.1.5:6379,server_type=primary,redis_connection=Redis<ConnectionPool<Connection<host=10.244.1.5,port=6379,db=0>>>], [host=10.244.1.6,port=6379,name=10.244.1.6:6379,server_type=replica,redis_connection=Redis<ConnectionPool<Connection<host=10.244.1.6,port=6379,db=0>>>], [host=10.244.2.7,port=6379,name=10.244.2.7:6379,server_type=primary,redis_connection=Redis<ConnectionPool<Connection<host=10.244.2.7,port=6379,db=0>>>], [host=10.244.0.9,port=6379,name=10.244.0.9:6379,server_type=replica,redis_connection=Redis<ConnectionPool<Connection<host=10.244.0.9,port=6379,db=0>>>]]\n \n Set and get some values. \n rc.set(\"one\", \"goodbye\")\nrc.get(\"two\")\n \n Finally, create a loop that will https://redis.io/commands/lpush the current time to now every two seconds. \n import datetime, time\nwhile True:\n now = datetime.datetime.now().strftime(\"%H:%M:%S\")\n rc.lpush('now', now)\n time.sleep(2)\n \n You will see the length of the list increase. \n >>> import datetime, time\n>>> while True:\n... now = datetime.datetime.now().strftime(\"%H:%M:%S\")\n... rc.lpush('now', now)\n... time.sleep(2)\n... \n1\n2\n3\n \n Switch to the terminal where you ran redis-cli in the my-redis-redis-cluster-client pod, and run rpop now repeatedly. \n 10.244.0.6:6379> rpop now\n\"18:33:14\"\n10.244.0.6:6379> rpop now\n\"18:33:16\"\n10.244.0.6:6379> rpop now\n\"18:33:18\"\n10.244.0.6:6379> \n \n   \n Explore with Go \n Finally, we will deploy the pre-built container application that will log our new items. This provides an example of how to use the https://github.com/go-redis/redis package. This example uses the https://redis.uptrace.dev/guide/universal.html. \n   \n We provided a pre-built container at https://github.com/users/asw101/packages/container/package/go-redis-sample and you can view the full source code of the sample at https://github.com/asw101/go-redis-sample. The repo includes a https://github.com/asw101/go-redis-sample/blob/main/Dockerfile that uses https://github.com/GoogleContainerTools/distroless base image and helper scripts that allow you to run the same container to https://github.com/asw101/go-redis-sample/blob/main/do/kubectl-run.sh events (the default), https://github.com/asw101/go-redis-sample/blob/main/do/kubectl-run-produce.sh events, and replicates the Python example above. You can see the code for the https://github.com/asw101/go-redis-sample/blob/main/main.go#L62 and https://github.com/asw101/go-redis-sample/blob/main/main.go#L74 functions in https://github.com/asw101/go-redis-sample/blob/main/main.go, alongside a simple Set/Get https://github.com/asw101/go-redis-sample/blob/main/main.go#L90 from the original https://github.com/go-redis/redis#quickstart quickstart. \n   \n Make sure you have the previous Python snippet above running in a terminal. \n   \n In another terminal window, we will set the REDIS_PASSWORD environment variable as before, and also get the internal endpoints for the my-redis-redis-cluster service which we will provide to the REDIS_ADDR . \n   \n \n Set the REDIS_PASSWORD  and REDIS_ADDR  variables and then deploy the ghcr.io/asw101/go-redis-sample:v1  container. \n \n export REDIS_PASSWORD=$(kubectl get secret --namespace \"default\" my-redis-redis-cluster -o jsonpath=\"{.data.redis-password}\" | base64 --decode)\n\nexport REDIS_ADDR=$(kubectl get endpoints my-redis-redis-cluster -o=jsonpath='{.subsets[0].addresses[*].ip}')\n\nkubectl run --namespace default go-redis-sample \\\n --rm --tty -i --restart='Never' \\\n --env REDIS_PASSWORD=\"$REDIS_PASSWORD\" \\\n --env REDIS_ADDR=\"$REDIS_ADDR\" \\\n --image ghcr.io/asw101/go-redis-sample:v1\n \n To run the above as a producer, replacing the Python snippet above, you can use the https://github.com/asw101/go-redis-sample/blob/main/do/kubectl-run-produce.sh script in the repo. https://github.com/asw101/go-redis-sample/blob/main/do/docker-buildx.sh is an example of the Docker build command for the image. \n   \n The go-redis https://redis.uptrace.dev/guide/universal.html lets us connect using single-node Client, a ClusterClient, or a FailoverClient, depending on whether a single endpoint, multiple endpoints, or a MasterName are provided. However, unlike the Python client, this snippet does not automatically discover the endpoints, and we are using the internal endpoints of the service for testing purposes only – do not do this in production. Finally, you may wonder why we cannot use kubectl port-forward to the my-redis-redis-cluster service and use that for local testing. This is because the client will attempt to connect to each shard directly, which will not be possible as your machine will not be able to reach those endpoints via the port-forward. \n   \n Finally, if you want to continue to hack on this inside the cluster, without any other dependencies, you could run https://github.com/asw101/nvgo/blob/main/do/kubectl-nvgo.sh container insider your cluster. It uses https://neovim.io/, https://pkg.go.dev/golang.org/x/tools/gopls language server in the official https://hub.docker.com/_/golang Docker image. \n   \n Summary \n In this post you have deployed Redis Cluster to your AKS cluster with helm, explored it interactively with the Redis CLI and Python, as well as a pre-built Go container. \n   \n At this stage, you may wish to build another container in the language of your choice to future explore Redis within your Kubernetes environment. Or perhaps even try it with https://docs.dapr.io/getting-started/configure-state-pubsub/ or https://keda.sh/docs/2.6/scalers/redis-lists/. \n   \n Once you have finished exploring, you should delete the my-aks resource group for your AKS cluster to avoid any further charges. \n az group delete -n my-aks\n \n   \n by https://twitter.com/as_w \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"16293","kudosSumWeight":3,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:4400609":{"__typename":"Conversation","id":"conversation:4400609","topic":{"__typename":"BlogTopicMessage","uid":4400609},"lastPostingActivityTime":"2025-04-15T09:29:10.991-07:00","solved":false},"User:user:1400175":{"__typename":"User","uid":1400175,"login":"fiveisprime","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/dS0xNDAwMTc1LXc0RmlLMg?image-coordinates=1%2C0%2C1400%2C1398"},"id":"user:1400175"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00NDAwNjA5LTFRSXJReA?revision=6\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00NDAwNjA5LTFRSXJReA?revision=6","title":"image.png","associationType":"BODY","width":973,"height":159,"altText":""},"BlogTopicMessage:message:4400609":{"__typename":"BlogTopicMessage","subject":"Major Updates to VS Code Docker: Introducing Container Tools","conversation":{"__ref":"Conversation:conversation:4400609"},"id":"message:4400609","revisionNum":6,"uid":4400609,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:1400175"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"The world of software development is ever evolving, and with it, the tools we use must adapt and improve. The Docker extension is no exception. We are thrilled to announce significant updates that will open new opportunities for your development experience. Here's a comprehensive overview of what's coming your way.","metrics":{"__typename":"MessageMetrics","views":21500},"postTime":"2025-04-15T08:59:33.954-07:00","lastPublishTime":"2025-04-15T09:29:10.991-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n The first, most obvious thing is the introduction of the Container Tools extension to broaden our focus and open new extensibility opportunities. The existing extension code (and MIT license) will be migrated to the Container Tools extension, and the Docker extension will become an extension pack that includes the Docker DX and Container Tools extensions. For you, this means the ability to customize the tooling to meet your needs - choose your preferred container runtime and only the functionality that you need in the extension settings. \n This major update marks a significant step forward in enhancing the development experience when working with containers. Please comment here with any questions or feedback and stay tuned to experiment with the new features! \n   \n tl;dr  \n \n The Docker extension is becoming the Container Tools extension \n Still free and open source \n Podman support is coming \n No action is required \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"948","kudosSumWeight":9,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS00NDAwNjA5LTFRSXJReA?revision=6\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"Conversation:conversation:3973401":{"__typename":"Conversation","id":"conversation:3973401","topic":{"__typename":"BlogTopicMessage","uid":3973401},"lastPostingActivityTime":"2025-06-03T07:11:01.799-07:00","solved":false},"User:user:1222039":{"__typename":"User","uid":1222039,"login":"kaysieyu","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/m_assets/avatars/default/avatar-11.svg?time=0"},"id":"user:1222039"},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNWk1NEYwNEY2Q0VDRDZGODFD?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNWk1NEYwNEY2Q0VDRDZGODFD?revision=4","title":"kaysieyu_0-1699239673768.png","associationType":"BODY","width":1397,"height":882,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNmlFMTY5NDVDRUY0M0UyQTdB?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNmlFMTY5NDVDRUY0M0UyQTdB?revision=4","title":"kaysieyu_1-1699239673792.png","associationType":"BODY","width":1397,"height":881,"altText":null},"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNGlBN0Q1MjRBRjA3MTMxRTU3?revision=4\"}":{"__typename":"AssociatedImage","url":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNGlBN0Q1MjRBRjA3MTMxRTU3?revision=4","title":"kaysieyu_2-1699239673818.png","associationType":"BODY","width":1400,"height":884,"altText":null},"BlogTopicMessage:message:3973401":{"__typename":"BlogTopicMessage","subject":"AKS Cost Analysis: an Azure-native cost visibility experience built on the OpenCost project","conversation":{"__ref":"Conversation:conversation:3973401"},"id":"message:3973401","revisionNum":4,"uid":3973401,"depth":0,"board":{"__ref":"Blog:board:AppsonAzureBlog"},"author":{"__ref":"User:user:1222039"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Granular breakdown of AKS cluster infrastructure costs by Kubernetes-specific constructs directly in the Azure Portal. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":18299},"postTime":"2023-11-06T06:00:00.032-08:00","lastPublishTime":"2024-01-12T14:37:48.160-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" With containers becoming the new normal for cloud operations, the adoption of Kubernetes, by cloud native and enterprise organizations alike, continues to skyrocket. The 2022 CNCF Annual Survey touts Kubernetes as “the ‘operating system’ of the cloud,” as it has become the platform for running almost any kind of workload. Cost optimization, however, continues to be a top challenge for organizations regardless of their level of maturity and experience adopting Kubernetes. \n   \n Organizations are looking for ways to reduce cloud spend, but without cost visibility and allocation tooling it is difficult to know where to start and what to optimize. In the 2023 State of FinOps Survey, cost allocation remained the #1 most prioritized FinOps capability by practitioners. Additionally, “creating visibility and transparency to cloud costs” was the most popular initiative organizations use to establish a FinOps culture for 71% of respondents. \n   \n Why is cost visibility so important? \n Visibility into Kubernetes cluster resource costs is vital to achieve the following: \n \n Cost allocation – ensure costs are attributed to the right teams, so they are aware and accountable. Accountability helps drive effective cost management. \n Optimization opportunities – pinpoint high spend clusters and resources that may require additional or better management. This is a jumping off point for implementing other Azure Kubernetes Service (AKS) cost management best practices to right size clusters and workloads. \n Anomaly detection – proactively identify anomalous or inconsistent spending patterns. Early detection will prevent unanticipated overspending. \n \n Ultimately, increased transparency into what makes up a cluster’s cost can help your organization have a better understanding and approach to managing costs. \n   \n Introducing the AKS Cost Analysis add-on \n To solve the cost visibility challenge, we are excited to announce the preview of the AKS Cost Analysis add-on, an Azure native experience that enables granular breakdown of AKS cluster costs. This add-on is built on the OpenCost project and available for Standard and Premium tier AKS clusters at no additional cost. Cost allocation data is reported directly in the Azure Portal. \n   \n AKS is the first Azure service to provide service-specific cost drill downs. What does this mean for customers? Azure Cost Management will now offer Kubernetes-specific views in the Cost Analysis UI to show cost allocation of AKS cluster infrastructure resources (ex: VMSS, public IPs, disks, etc.) by Kubernetes specific constructs like cluster and namespace. This added granularity will help organizations understand exactly how much individual applications cost and which clusters or applications need optimization. \n   \n Shared costs such as idle, system reserved, and service SLA costs, which typically can’t be apportioned to a specific namespace are also reported. This gives organizations the flexibility to allocate shared costs in the way that works best for their scenario – proportionally, by fixed percentage, uniformly etc. \n   \n Here is a sneak peek of the new UI views: \n   \n \n New Kubernetes Cluster view. \n   \n \n New Kubernetes Namespaces view. \n   \n \n New Kubernetes Assets view. \n   \n AKS Cost Analysis is built on OpenCost for node and container usage metrics collection. OpenCost is an open-source, vendor-neutral CNCF sandbox project and FinOps Certified Solution with original code provided by Kubecost. Microsoft has contributed to the project and works closely with the OpenCost maintainers to ensure project compatibility for this implementation. If you are looking to get involved with OpenCost or have questions about the project, check out the project on GitHub, join the #opencost channel in the CNCF Slack, and attend the community meetings. Thank you OpenCost team and community! \n   \n Where can I learn more? \n Stay tuned for more information on the AKS Cost Analysis add-on at Microsoft Ignite 2023 (November 14 – 17). Keep an eye out for an Azure update. Reference the AKS Cost Analysis add-on docs. View a recent AKS + Kubecost webinar titled \"Tools and Tips for Unparalleled Cost Transparency on AKS\" for a demo of the add-on and to learn how OpenCost and Kubecost can also help with your cost management scenario. \n   \n For questions, please join us at the Microsoft Azure booth at KubeCon + CloudNativeCon North America 2023. We will have a demo at our booth on Tuesday, November 7 th at 2:45pm Central Time. \n   \n We will also be at the Microsoft Azure booth at Ignite 2023. Hope to see you there! \n   ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4698","kudosSumWeight":4,"repliesCount":10,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNWk1NEYwNEY2Q0VDRDZGODFD?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNmlFMTY5NDVDRUY0M0UyQTdB?revision=4\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://techcommunity.microsoft.com/t5/s/gxcuf89792/images/bS0zOTczNDAxLTUyMjMxNGlBN0Q1MjRBRjA3MTMxRTU3?revision=4\"}"}}],"totalCount":3,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"coverImage":null,"coverImageProperties":{"__typename":"CoverImageProperties","style":"STANDARD","titlePosition":"BOTTOM","altText":""}},"CachedAsset:text:en_US-components/community/Navbar-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1747867729000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","gxcuf89792":"Tech Community","external-1":"Events","s-m-b":"Nonprofit Community","windows-server":"Windows Server","education-sector":"Education Sector","driving-adoption":"Driving Adoption","Common-content_management-link":"Content Management","microsoft-learn":"Microsoft Learn","s-q-l-server":"Content Management","partner-community":"Microsoft Partner Community","microsoft365":"Microsoft 365","external-9":".NET","external-8":"Teams","external-7":"Github","products-services":"Products","external-6":"Power Platform","communities-1":"Topics","external-5":"Microsoft Security","planner":"Outlook","external-4":"Microsoft 365","external-3":"Dynamics 365","azure":"Azure","healthcare-and-life-sciences":"Healthcare and Life Sciences","external-2":"Azure","microsoft-mechanics":"Microsoft Mechanics","microsoft-learn-1":"Community","external-10":"Learning Room Directory","microsoft-learn-blog":"Blog","windows":"Windows","i-t-ops-talk":"ITOps Talk","external-link-1":"View All","microsoft-securityand-compliance":"Microsoft Security","public-sector":"Public Sector","community-info-center":"Lounge","external-link-2":"View All","microsoft-teams":"Microsoft Teams","external":"Blogs","microsoft-endpoint-manager":"Microsoft Intune","startupsat-microsoft":"Startups at Microsoft","exchange":"Exchange","a-i":"AI and Machine Learning","io-t":"Internet of Things (IoT)","Common-microsoft365-copilot-link":"Microsoft 365 Copilot","outlook":"Microsoft 365 Copilot","external-link":"Community Hubs","communities":"Products"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1747867729000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1747867729000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1747867729000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1747867729000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1747867729000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagSubscriptionAction-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagSubscriptionAction-1747867729000","value":{"success.follow.title":"Following Tag","success.unfollow.title":"Unfollowed Tag","success.follow.message.followAcrossCommunity":"You will be notified when this tag is used anywhere across the community","success.unfollowtag.message":"You will no longer be notified when this tag is used anywhere in this place","success.unfollowtagAcrossCommunity.message":"You will no longer be notified when this tag is used anywhere across the community","unexpected.error.title":"Error - Action Failed","unexpected.error.message":"An unidentified problem occurred during the action you took. Please try again later.","buttonTitle":"{isSubscribed, select, true {Unfollow} false {Follow} other{}}","unfollow":"Unfollow"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1747867729000","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1747867729000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1747867729000","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListTabs-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListTabs-1747867729000","value":{"mostKudoed":"{value, select, IDEA {Most Votes} other {Most Likes}}","mostReplies":"Most Replies","mostViewed":"Most Viewed","newest":"{value, select, IDEA {Newest Ideas} OCCASION {Newest Events} other {Newest Topics}}","newestOccasions":"Newest Events","mostRecent":"Most Recent","noReplies":"No Replies Yet","noSolutions":"No Solutions Yet","solutions":"Solutions","mostRecentUserContent":"Most Recent","trending":"Trending","draft":"Drafts","spam":"Spam","abuse":"Abuse","moderation":"Moderation","tags":"Tags","PAST":"Past","UPCOMING":"Upcoming","sortBymostRecent":"Sort By Most Recent","sortBymostRecentUserContent":"Sort By Most Recent","sortBymostKudoed":"Sort By Most Likes","sortBymostReplies":"Sort By Most Replies","sortBymostViewed":"Sort By Most Viewed","sortBynewest":"Sort By Newest Topics","sortBynewestOccasions":"Sort By Newest Events","otherTabs":" Messages list in the {tab} for {conversationStyle}","guides":"Guides","archives":"Archives"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewInline-1747867729000","value":{"bylineAuthor":"{bylineAuthor}","bylineBoard":"{bylineBoard}","anonymous":"Anonymous","place":"Place {bylineBoard}","gotoParent":"Go to parent {name}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Pager/PagerLoadMore-1747867729000","value":{"loadMore":"Show More"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/OverflowNav-1747867729000","value":{"toggleText":"More"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1747867729000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1747867729000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1747867729000","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1747867729000","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageUnreadCount-1747867729000","value":{"unread":"{count} unread","comments":"{count, plural, one { unread comment} other{ unread comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageViewCount-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageViewCount-1747867729000","value":{"textTitle":"{count, plural,one {View} other{Views}}","views":"{count, plural, one{View} other{Views}}"},"localOverride":false},"CachedAsset:text:en_US-components/kudos/KudosCount-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/kudos/KudosCount-1747867729000","value":{"textTitle":"{count, plural,one {{messageType, select, IDEA{Vote} other{Like}}} other{{messageType, select, IDEA{Votes} other{Likes}}}}","likes":"{count, plural, one{like} other{likes}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRepliesCount-1747867729000","value":{"textTitle":"{count, plural,one {{conversationStyle, select, IDEA{Comment} OCCASION{Comment} other{Reply}}} other{{conversationStyle, select, IDEA{Comments} OCCASION{Comments} other{Replies}}}}","comments":"{count, plural, one{Comment} other{Comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1747867729000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1747867729000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1747867729000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false}}}},"page":"/tags/TagPage/TagPage","query":{"messages.widget.messagelistfornodebyrecentactivitywidget-tab-main-messages-list-for-tag-widget-0":"mostViewed","nodeId":"board:AppsonAzureBlog","tagName":"containers"},"buildId":"cQon2PUqbQU8la6pXifn2","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"o365","openTelemetryServiceVersion":"25.3.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/customComponent/CustomComponent/CustomComponent.tsx","./components/tags/TagsHeaderWidget/TagsHeaderWidget.tsx","./components/messages/MessageListForNodeByRecentActivityWidget/MessageListForNodeByRecentActivityWidget.tsx","./components/tags/TagSubscriptionAction/TagSubscriptionAction.tsx","./components/external/components/ExternalComponent.tsx","./components/customComponent/CustomComponentContent/HtmlContent.tsx","../shared/client/components/common/List/ListGroup/ListGroup.tsx","./components/messages/MessageView/MessageView.tsx","./components/messages/MessageView/MessageViewInline/MessageViewInline.tsx","../shared/client/components/common/Pager/PagerLoadMore/PagerLoadMore.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx","./components/customComponent/CustomComponentContent/CustomComponentScripts.tsx"],"appGip":true,"scriptLoader":[{"id":"analytics","src":"https://techcommunity.microsoft.com/t5/s/gxcuf89792/pagescripts/1730819800000/analytics.js?page.id=TagPage","strategy":"afterInteractive"}]}
OSZAR »